Message ID | 20200630192441.3299710-7-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | [1/7] sysv: linux: Add 64-bit time_t variant for semctl | expand |
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
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)?
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
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.
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
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>
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
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
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.
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; +};