From patchwork Tue Jun 30 19:24:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 1320098 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=libc-alpha-bounces@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=sourceware.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=Ao1ZLRKX; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49xDpW1BXrz9sQt for ; Wed, 1 Jul 2020 05:25:23 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5AD2D3851C11; Tue, 30 Jun 2020 19:25:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5AD2D3851C11 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1593545103; bh=pDxNq0kT2XRKkbV+UO5gHwAxCMJhGFshREklPBC+0z0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Ao1ZLRKXDIz3/1nm1nuLJFhPEkWTipfWw+qKZUnIAFreJs/FH8T7hexUXi3vyIPP5 ZPEJzWeOpm9nk/hefJtCnZ9CffCzTWuWE5zUS9n5+l9Q4f+5AcbMnohuPT2j/+A0Ly nWxNRiKS1M+30ndKPkfPm9jL3A8DfxtQ8EgoEhW0= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x842.google.com (mail-qt1-x842.google.com [IPv6:2607:f8b0:4864:20::842]) by sourceware.org (Postfix) with ESMTPS id 081FB3851C17 for ; Tue, 30 Jun 2020 19:24:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 081FB3851C17 Received: by mail-qt1-x842.google.com with SMTP id u17so16536350qtq.1 for ; Tue, 30 Jun 2020 12:24:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pDxNq0kT2XRKkbV+UO5gHwAxCMJhGFshREklPBC+0z0=; b=LtJFPUmlF2XZLldAbvJU3P4f3HEUMqdQolFTjoD6DAAS1hoQBS6GTKamkN9Zqrv7+3 4pg8uPmGS2dXTjXq87T49lQQUjPUOfvk3kSPLOzmWgSdxhzSv8CF3qsVGmyge83j0/th SeorVqiMxvlu/BpR6wNSNiq2ytz50g3ut81x9T7CL6ELDupeEddAVcC2j2HXjlhfMZcD imrctsc39aOAjD6cOK57Fu92xCRH7Ekt6e5nZbChvvaST8DCYvvzJOK2ucKnW7yK38mP S8UITkViKZ4G92Zh9QYsCeXMhANF6gsk3f4EWEdL2Jcwk1RnblVbBlYhG4iCZG7lTuNS 9vdg== X-Gm-Message-State: AOAM530WD871o1gq6mZrPNQDZHdlDT1QbR9Up1HeHO6Zkx5NwslX6r6q LV4feKuQmFAaoilhR8pgmBx1XgjFmlI= X-Google-Smtp-Source: ABdhPJye+uasOyBKNXWiv3RJZPLehvgtZ5dIMO5FjAoJSf2nwIRQyKZPIrMJtFofNpfPgHA07mEymQ== X-Received: by 2002:ac8:a44:: with SMTP id f4mr3890960qti.348.1593545096714; Tue, 30 Jun 2020 12:24:56 -0700 (PDT) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id b7sm3558214qkl.18.2020.06.30.12.24.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jun 2020 12:24:56 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl Date: Tue, 30 Jun 2020 16:24:41 -0300 Message-Id: <20200630192441.3299710-7-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200630192441.3299710-1-adhemerval.zanella@linaro.org> References: <20200630192441.3299710-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-14.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Cc: stepan@golosunov.pp.ru, Alistair Francis Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" 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. Tested-by: Carlos O'Donell Reviewed-by: Carlos O'Donell --- 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 + +#ifndef _ISOMAC + +# include + +# 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 + . */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use 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 #include /* 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 + +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; +};