Message ID | 20200305012605.26870-4-alistair.francis@wdc.com |
---|---|
State | New |
Headers | show |
Series | Support y2038 semctl_syscall() | expand |
On Mär 04 2020, Alistair Francis wrote: > We protect this new code via the __IPC_TIME64 marco, which is only true > for 32-bit architectures with a 64-bit time_t. There is only a single use of the macro, so I don't see much point in it. > diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c > index 0c3eb0932f..3ac6d01b84 100644 > --- a/sysdeps/unix/sysv/linux/semctl.c > +++ b/sysdeps/unix/sysv/linux/semctl.c > @@ -23,11 +23,16 @@ > #include <shlib-compat.h> > #include <errno.h> > > +#define __IPC_TIME64 (IPC_STAT & __IPC_64) > + > /* Define a `union semun' suitable for Linux here. */ > union semun > { > int val; /* value for SETVAL */ > struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ > +#if __WORDSIZE == 32 > + struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */ Currently, this is only used for IPC_STAT. > +#endif > unsigned short int *array; /* array for GETALL & SETALL */ > struct seminfo *__buf; /* buffer for IPC_INFO */ > }; > @@ -43,13 +48,25 @@ union semun > static int > semctl_syscall (int semid, int semnum, int cmd, union semun arg) > { > + int ret; > #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS > - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > - arg.array); > + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > + arg.array); > #else > - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > - SEMCTL_ARG_ADDRESS (arg)); > + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > + SEMCTL_ARG_ADDRESS (arg)); > +#endif > + > +#if __IPC_TIME64 > + if (ret == 0 && (cmd & __IPC_TIME64)) I don't think that's the right condition. IIUC this should check for cmd == IPC_STAT. Andreas.
On Thu, Mar 5, 2020 at 2:14 AM Andreas Schwab <schwab@suse.de> wrote: > > On Mär 04 2020, Alistair Francis wrote: > > > We protect this new code via the __IPC_TIME64 marco, which is only true > > for 32-bit architectures with a 64-bit time_t. > > There is only a single use of the macro, so I don't see much point in > it. This came from comments from Adhemerval Zanella on the previous version which you can see here: https://patchwork.ozlabs.org/patch/1233625/#2367606 > > > diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c > > index 0c3eb0932f..3ac6d01b84 100644 > > --- a/sysdeps/unix/sysv/linux/semctl.c > > +++ b/sysdeps/unix/sysv/linux/semctl.c > > @@ -23,11 +23,16 @@ > > #include <shlib-compat.h> > > #include <errno.h> > > > > +#define __IPC_TIME64 (IPC_STAT & __IPC_64) > > + > > /* Define a `union semun' suitable for Linux here. */ > > union semun > > { > > int val; /* value for SETVAL */ > > struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ > > +#if __WORDSIZE == 32 > > + struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */ > > Currently, this is only used for IPC_STAT. I'll update the comment. > > > +#endif > > unsigned short int *array; /* array for GETALL & SETALL */ > > struct seminfo *__buf; /* buffer for IPC_INFO */ > > }; > > @@ -43,13 +48,25 @@ union semun > > static int > > semctl_syscall (int semid, int semnum, int cmd, union semun arg) > > { > > + int ret; > > #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS > > - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > > - arg.array); > > + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > > + arg.array); > > #else > > - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > > - SEMCTL_ARG_ADDRESS (arg)); > > + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > > + SEMCTL_ARG_ADDRESS (arg)); > > +#endif > > + > > +#if __IPC_TIME64 > > + if (ret == 0 && (cmd & __IPC_TIME64)) > > I don't think that's the right condition. IIUC this should check for > cmd == IPC_STAT. I'm not sure, I'll check to see what it should be. Alistair > > Andreas. > > -- > Andreas Schwab, SUSE Labs, schwab@suse.de > GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 > "And now for something completely different."
Hi Alistair, On 3/4/20 5:26 PM, Alistair Francis wrote: > The semctl_syscall() function passes a union semun to the kernel. The > union includes struct semid_ds as a member. On 32-bit architectures the > Linux kernel provides a *_high version of the 32-bit sem_otime and > sem_ctime values. These can be combined to get a 64-bit version of the > time. > > This patch adjusts the struct semid_ds to support the *_high versions > of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t > this can be used to get a 64-bit time from the two 32-bit values. > > We protect this new code via the __IPC_TIME64 marco, which is only true > for 32-bit architectures with a 64-bit time_t. > --- > bits/ipc.h | 6 ++++- > sysdeps/gnu/bits/ipc.h | 6 ++++- > sysdeps/unix/sysv/linux/bits/ipc.h | 6 ++++- > sysdeps/unix/sysv/linux/bits/semid_ds_t.h | 15 +++++++++++ > .../unix/sysv/linux/hppa/bits/semid_ds_t.h | 15 +++++++++++ > .../unix/sysv/linux/mips/bits/semid_ds_t.h | 13 ++++++++++ > .../unix/sysv/linux/powerpc/bits/semid_ds_t.h | 15 +++++++++++ > sysdeps/unix/sysv/linux/semctl.c | 25 ++++++++++++++++--- > .../unix/sysv/linux/sparc/bits/semid_ds_t.h | 15 +++++++++++ > sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h | 15 +++++++++++ > 10 files changed, 124 insertions(+), 7 deletions(-) > > diff --git a/bits/ipc.h b/bits/ipc.h > index e2981fd5c3..9ac8485193 100644 > --- a/bits/ipc.h > +++ b/bits/ipc.h > @@ -29,7 +29,11 @@ > /* Control commands for `msgctl', `semctl', and `shmctl'. */ > #define IPC_RMID 0 /* remove identifier */ > #define IPC_SET 1 /* set `ipc_perm' options */ > -#define IPC_STAT 2 /* get `ipc_perm' options */ > +#if __TIMESIZE == 64 && __WORDSIZE == 32 > +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ > +#else > +# define IPC_STAT 2 /* Get `ipc_perm' options. */ > +#endif Why is this needed. Linux kernel seems to be returning EINVAL for this cmd-id and following fail for ARC. FAIL: sysvipc/test-sysvmsg FAIL: sysvipc/test-sysvsem FAIL: sysvipc/test-sysvshm Shouldn't this use the default __IPC_64 value which is 0 not 0x100. > > /* Special key values. */ > #define IPC_PRIVATE ((key_t) 0) /* private key */ > diff --git a/sysdeps/gnu/bits/ipc.h b/sysdeps/gnu/bits/ipc.h > index 47df305e1c..328c11a0d7 100644 > --- a/sysdeps/gnu/bits/ipc.h > +++ b/sysdeps/gnu/bits/ipc.h > @@ -29,7 +29,11 @@ > /* Control commands for `msgctl', `semctl', and `shmctl'. */ > #define IPC_RMID 0 /* Remove identifier. */ > #define IPC_SET 1 /* Set `ipc_perm' options. */ > -#define IPC_STAT 2 /* Get `ipc_perm' options. */ > +#if __TIMESIZE == 64 && __WORDSIZE == 32 > +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ > +#else > +# define IPC_STAT 2 /* Get `ipc_perm' options. */ > +#endif > #ifdef __USE_GNU > # define IPC_INFO 3 /* See ipcs. */ > #endif > diff --git a/sysdeps/unix/sysv/linux/bits/ipc.h b/sysdeps/unix/sysv/linux/bits/ipc.h > index 085dd628ac..44449de62f 100644 > --- a/sysdeps/unix/sysv/linux/bits/ipc.h > +++ b/sysdeps/unix/sysv/linux/bits/ipc.h > @@ -29,7 +29,11 @@ > /* Control commands for `msgctl', `semctl', and `shmctl'. */ > #define IPC_RMID 0 /* Remove identifier. */ > #define IPC_SET 1 /* Set `ipc_perm' options. */ > -#define IPC_STAT 2 /* Get `ipc_perm' options. */ > +#if __TIMESIZE == 64 && __WORDSIZE == 32 > +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ > +#else > +# define IPC_STAT 2 /* Get `ipc_perm' options. */ > +#endif > #ifdef __USE_GNU > # define IPC_INFO 3 /* See ipcs. */ > #endif > diff --git a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h > index d9d902ed0d..b135301356 100644 > --- a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h > +++ b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h > @@ -20,6 +20,21 @@ > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > #endif > > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif > + > /* Data structure describing a set of semaphores. */ > #if __TIMESIZE == 32 > struct semid_ds > diff --git a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h > index 39c0e53f38..3613c5ec94 100644 > --- a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h > +++ b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h > @@ -20,6 +20,21 @@ > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > #endif > > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif > + > /* Data structure describing a set of semaphores. */ > #if __TIMESIZE == 32 > struct semid_ds > diff --git a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h > index 1ab16492dd..e26906a67f 100644 > --- a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h > +++ b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h > @@ -20,6 +20,19 @@ > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > #endif > > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime; /* last semop time */ > + __syscall_ulong_t sem_ctime; /* last change time */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t sem_otime_high; > + __syscall_ulong_t sem_ctime_high; > +}; > +#endif > + > /* Data structure describing a set of semaphores. */ > struct semid_ds > { > diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h > index 79b4cba939..ec2ff552eb 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h > +++ b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h > @@ -20,6 +20,21 @@ > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > #endif > > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif > + > /* Data structure describing a set of semaphores. */ > #if __TIMESIZE == 32 > struct semid_ds > diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c > index 0c3eb0932f..3ac6d01b84 100644 > --- a/sysdeps/unix/sysv/linux/semctl.c > +++ b/sysdeps/unix/sysv/linux/semctl.c > @@ -23,11 +23,16 @@ > #include <shlib-compat.h> > #include <errno.h> > > +#define __IPC_TIME64 (IPC_STAT & __IPC_64) > + > /* Define a `union semun' suitable for Linux here. */ > union semun > { > int val; /* value for SETVAL */ > struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ > +#if __WORDSIZE == 32 > + struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */ > +#endif > unsigned short int *array; /* array for GETALL & SETALL */ > struct seminfo *__buf; /* buffer for IPC_INFO */ > }; > @@ -43,13 +48,25 @@ union semun > static int > semctl_syscall (int semid, int semnum, int cmd, union semun arg) > { > + int ret; > #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS > - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > - arg.array); > + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > + arg.array); > #else > - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > - SEMCTL_ARG_ADDRESS (arg)); > + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > + SEMCTL_ARG_ADDRESS (arg)); > +#endif > + > +#if __IPC_TIME64 > + if (ret == 0 && (cmd & __IPC_TIME64)) > + { > + arg.buf->sem_ctime = arg.buf32->sem_ctime | > + ((time_t) arg.buf32->sem_ctime_high << 32); > + arg.buf->sem_otime = arg.buf32->sem_otime | > + ((time_t) arg.buf32->sem_otime_high << 32); > + } > #endif > + return ret; > } > > int > diff --git a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h > index f8de676e79..b08fb8a79e 100644 > --- a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h > +++ b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h > @@ -20,6 +20,21 @@ > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > #endif > > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif > + > /* Data structure describing a set of semaphores. */ > #if __TIMESIZE == 32 > struct semid_ds > diff --git a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h > index 42694069d5..c7b9adce88 100644 > --- a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h > +++ b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h > @@ -20,6 +20,21 @@ > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > #endif > > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif > + > /* Data structure describing a set of semaphores. */ > struct semid_ds > { >
On 3/10/20 5:29 PM, Vineet Gupta via Libc-alpha wrote: > Hi Alistair, > > On 3/4/20 5:26 PM, Alistair Francis wrote: >> The semctl_syscall() function passes a union semun to the kernel. The >> union includes struct semid_ds as a member. On 32-bit architectures the >> Linux kernel provides a *_high version of the 32-bit sem_otime and >> sem_ctime values. These can be combined to get a 64-bit version of the >> time. >> >> This patch adjusts the struct semid_ds to support the *_high versions >> of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t >> this can be used to get a 64-bit time from the two 32-bit values. >> >> We protect this new code via the __IPC_TIME64 marco, which is only true >> for 32-bit architectures with a 64-bit time_t. [snip...] >> >> diff --git a/bits/ipc.h b/bits/ipc.h >> index e2981fd5c3..9ac8485193 100644 >> --- a/bits/ipc.h >> +++ b/bits/ipc.h >> @@ -29,7 +29,11 @@ >> /* Control commands for `msgctl', `semctl', and `shmctl'. */ >> #define IPC_RMID 0 /* remove identifier */ >> #define IPC_SET 1 /* set `ipc_perm' options */ >> -#define IPC_STAT 2 /* get `ipc_perm' options */ >> +#if __TIMESIZE == 64 && __WORDSIZE == 32 >> +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ >> +#else >> +# define IPC_STAT 2 /* Get `ipc_perm' options. */ >> +#endif > > Why is this needed. Linux kernel seems to be returning EINVAL for this cmd-id and > following fail for ARC. > > FAIL: sysvipc/test-sysvmsg > FAIL: sysvipc/test-sysvsem > FAIL: sysvipc/test-sysvshm > > Shouldn't this use the default __IPC_64 value which is 0 not 0x100. > >> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c >> index 0c3eb0932f..3ac6d01b84 100644 >> --- a/sysdeps/unix/sysv/linux/semctl.c >> +++ b/sysdeps/unix/sysv/linux/semctl.c >> @@ -23,11 +23,16 @@ >> #include <shlib-compat.h> >> #include <errno.h> >> >> +#define __IPC_TIME64 (IPC_STAT & __IPC_64) So __IPC_TIME64 can only happen if we have 0x102 based cmd ? But doesn't asm-generic ABI preclude the 0x100 ? >> + >> /* Define a `union semun' suitable for Linux here. */ >> union semun >> { >> int val; /* value for SETVAL */ >> struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ >> +#if __WORDSIZE == 32 >> + struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */ >> +#endif >> unsigned short int *array; /* array for GETALL & SETALL */ >> struct seminfo *__buf; /* buffer for IPC_INFO */ >> }; >> @@ -43,13 +48,25 @@ union semun >> static int >> semctl_syscall (int semid, int semnum, int cmd, union semun arg) >> { >> + int ret; >> #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS >> - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, >> - arg.array); >> + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, >> + arg.array); >> #else >> - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, >> - SEMCTL_ARG_ADDRESS (arg)); >> + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, >> + SEMCTL_ARG_ADDRESS (arg)); >> +#endif >> + >> +#if __IPC_TIME64 >> + if (ret == 0 && (cmd & __IPC_TIME64)) >> + { >> + arg.buf->sem_ctime = arg.buf32->sem_ctime | >> + ((time_t) arg.buf32->sem_ctime_high << 32); >> + arg.buf->sem_otime = arg.buf32->sem_otime | >> + ((time_t) arg.buf32->sem_otime_high << 32); >> + } >> #endif >> + return ret; >> }
On Tue, Mar 10, 2020 at 5:29 PM Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote: > > Hi Alistair, > > On 3/4/20 5:26 PM, Alistair Francis wrote: > > The semctl_syscall() function passes a union semun to the kernel. The > > union includes struct semid_ds as a member. On 32-bit architectures the > > Linux kernel provides a *_high version of the 32-bit sem_otime and > > sem_ctime values. These can be combined to get a 64-bit version of the > > time. > > > > This patch adjusts the struct semid_ds to support the *_high versions > > of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t > > this can be used to get a 64-bit time from the two 32-bit values. > > > > We protect this new code via the __IPC_TIME64 marco, which is only true > > for 32-bit architectures with a 64-bit time_t. > > --- > > bits/ipc.h | 6 ++++- > > sysdeps/gnu/bits/ipc.h | 6 ++++- > > sysdeps/unix/sysv/linux/bits/ipc.h | 6 ++++- > > sysdeps/unix/sysv/linux/bits/semid_ds_t.h | 15 +++++++++++ > > .../unix/sysv/linux/hppa/bits/semid_ds_t.h | 15 +++++++++++ > > .../unix/sysv/linux/mips/bits/semid_ds_t.h | 13 ++++++++++ > > .../unix/sysv/linux/powerpc/bits/semid_ds_t.h | 15 +++++++++++ > > sysdeps/unix/sysv/linux/semctl.c | 25 ++++++++++++++++--- > > .../unix/sysv/linux/sparc/bits/semid_ds_t.h | 15 +++++++++++ > > sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h | 15 +++++++++++ > > 10 files changed, 124 insertions(+), 7 deletions(-) > > > > diff --git a/bits/ipc.h b/bits/ipc.h > > index e2981fd5c3..9ac8485193 100644 > > --- a/bits/ipc.h > > +++ b/bits/ipc.h > > @@ -29,7 +29,11 @@ > > /* Control commands for `msgctl', `semctl', and `shmctl'. */ > > #define IPC_RMID 0 /* remove identifier */ > > #define IPC_SET 1 /* set `ipc_perm' options */ > > -#define IPC_STAT 2 /* get `ipc_perm' options */ > > +#if __TIMESIZE == 64 && __WORDSIZE == 32 > > +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ > > +#else > > +# define IPC_STAT 2 /* Get `ipc_perm' options. */ > > +#endif > > Why is this needed. Linux kernel seems to be returning EINVAL for this cmd-id and > following fail for ARC. > > FAIL: sysvipc/test-sysvmsg > FAIL: sysvipc/test-sysvsem > FAIL: sysvipc/test-sysvshm > > Shouldn't this use the default __IPC_64 value which is 0 not 0x100. I think you are right. I have fixed this up in the next version. Alistair > > > > > /* Special key values. */ > > #define IPC_PRIVATE ((key_t) 0) /* private key */ > > diff --git a/sysdeps/gnu/bits/ipc.h b/sysdeps/gnu/bits/ipc.h > > index 47df305e1c..328c11a0d7 100644 > > --- a/sysdeps/gnu/bits/ipc.h > > +++ b/sysdeps/gnu/bits/ipc.h > > @@ -29,7 +29,11 @@ > > /* Control commands for `msgctl', `semctl', and `shmctl'. */ > > #define IPC_RMID 0 /* Remove identifier. */ > > #define IPC_SET 1 /* Set `ipc_perm' options. */ > > -#define IPC_STAT 2 /* Get `ipc_perm' options. */ > > +#if __TIMESIZE == 64 && __WORDSIZE == 32 > > +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ > > +#else > > +# define IPC_STAT 2 /* Get `ipc_perm' options. */ > > +#endif > > #ifdef __USE_GNU > > # define IPC_INFO 3 /* See ipcs. */ > > #endif > > diff --git a/sysdeps/unix/sysv/linux/bits/ipc.h b/sysdeps/unix/sysv/linux/bits/ipc.h > > index 085dd628ac..44449de62f 100644 > > --- a/sysdeps/unix/sysv/linux/bits/ipc.h > > +++ b/sysdeps/unix/sysv/linux/bits/ipc.h > > @@ -29,7 +29,11 @@ > > /* Control commands for `msgctl', `semctl', and `shmctl'. */ > > #define IPC_RMID 0 /* Remove identifier. */ > > #define IPC_SET 1 /* Set `ipc_perm' options. */ > > -#define IPC_STAT 2 /* Get `ipc_perm' options. */ > > +#if __TIMESIZE == 64 && __WORDSIZE == 32 > > +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ > > +#else > > +# define IPC_STAT 2 /* Get `ipc_perm' options. */ > > +#endif > > #ifdef __USE_GNU > > # define IPC_INFO 3 /* See ipcs. */ > > #endif > > diff --git a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h > > index d9d902ed0d..b135301356 100644 > > --- a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h > > +++ b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h > > @@ -20,6 +20,21 @@ > > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > > #endif > > > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > + > > /* Data structure describing a set of semaphores. */ > > #if __TIMESIZE == 32 > > struct semid_ds > > diff --git a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h > > index 39c0e53f38..3613c5ec94 100644 > > --- a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h > > +++ b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h > > @@ -20,6 +20,21 @@ > > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > > #endif > > > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > + > > /* Data structure describing a set of semaphores. */ > > #if __TIMESIZE == 32 > > struct semid_ds > > diff --git a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h > > index 1ab16492dd..e26906a67f 100644 > > --- a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h > > +++ b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h > > @@ -20,6 +20,19 @@ > > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > > #endif > > > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime; /* last semop time */ > > + __syscall_ulong_t sem_ctime; /* last change time */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t sem_otime_high; > > + __syscall_ulong_t sem_ctime_high; > > +}; > > +#endif > > + > > /* Data structure describing a set of semaphores. */ > > struct semid_ds > > { > > diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h > > index 79b4cba939..ec2ff552eb 100644 > > --- a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h > > +++ b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h > > @@ -20,6 +20,21 @@ > > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > > #endif > > > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > + > > /* Data structure describing a set of semaphores. */ > > #if __TIMESIZE == 32 > > struct semid_ds > > diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c > > index 0c3eb0932f..3ac6d01b84 100644 > > --- a/sysdeps/unix/sysv/linux/semctl.c > > +++ b/sysdeps/unix/sysv/linux/semctl.c > > @@ -23,11 +23,16 @@ > > #include <shlib-compat.h> > > #include <errno.h> > > > > +#define __IPC_TIME64 (IPC_STAT & __IPC_64) > > + > > /* Define a `union semun' suitable for Linux here. */ > > union semun > > { > > int val; /* value for SETVAL */ > > struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ > > +#if __WORDSIZE == 32 > > + struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */ > > +#endif > > unsigned short int *array; /* array for GETALL & SETALL */ > > struct seminfo *__buf; /* buffer for IPC_INFO */ > > }; > > @@ -43,13 +48,25 @@ union semun > > static int > > semctl_syscall (int semid, int semnum, int cmd, union semun arg) > > { > > + int ret; > > #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS > > - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > > - arg.array); > > + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > > + arg.array); > > #else > > - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > > - SEMCTL_ARG_ADDRESS (arg)); > > + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > > + SEMCTL_ARG_ADDRESS (arg)); > > +#endif > > + > > +#if __IPC_TIME64 > > + if (ret == 0 && (cmd & __IPC_TIME64)) > > + { > > + arg.buf->sem_ctime = arg.buf32->sem_ctime | > > + ((time_t) arg.buf32->sem_ctime_high << 32); > > + arg.buf->sem_otime = arg.buf32->sem_otime | > > + ((time_t) arg.buf32->sem_otime_high << 32); > > + } > > #endif > > + return ret; > > } > > > > int > > diff --git a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h > > index f8de676e79..b08fb8a79e 100644 > > --- a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h > > +++ b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h > > @@ -20,6 +20,21 @@ > > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > > #endif > > > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > + > > /* Data structure describing a set of semaphores. */ > > #if __TIMESIZE == 32 > > struct semid_ds > > diff --git a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h > > index 42694069d5..c7b9adce88 100644 > > --- a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h > > +++ b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h > > @@ -20,6 +20,21 @@ > > # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." > > #endif > > > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > + > > /* Data structure describing a set of semaphores. */ > > struct semid_ds > > { > > >
On 3/18/20 4:11 PM, Alistair Francis via Libc-alpha wrote: >>> diff --git a/bits/ipc.h b/bits/ipc.h >>> index e2981fd5c3..9ac8485193 100644 >>> --- a/bits/ipc.h >>> +++ b/bits/ipc.h >>> @@ -29,7 +29,11 @@ >>> /* Control commands for `msgctl', `semctl', and `shmctl'. */ >>> #define IPC_RMID 0 /* remove identifier */ >>> #define IPC_SET 1 /* set `ipc_perm' options */ >>> -#define IPC_STAT 2 /* get `ipc_perm' options */ >>> +#if __TIMESIZE == 64 && __WORDSIZE == 32 >>> +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ >>> +#else >>> +# define IPC_STAT 2 /* Get `ipc_perm' options. */ >>> +#endif >> Why is this needed. Linux kernel seems to be returning EINVAL for this cmd-id and >> following fail for ARC. >> >> FAIL: sysvipc/test-sysvmsg >> FAIL: sysvipc/test-sysvsem >> FAIL: sysvipc/test-sysvshm >> >> Shouldn't this use the default __IPC_64 value which is 0 not 0x100. > I think you are right. I have fixed this up in the next version. Thx, that indeed fixes those tests for me - off of your latest branch. -Vineet
diff --git a/bits/ipc.h b/bits/ipc.h index e2981fd5c3..9ac8485193 100644 --- a/bits/ipc.h +++ b/bits/ipc.h @@ -29,7 +29,11 @@ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* remove identifier */ #define IPC_SET 1 /* set `ipc_perm' options */ -#define IPC_STAT 2 /* get `ipc_perm' options */ +#if __TIMESIZE == 64 && __WORDSIZE == 32 +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ +#else +# define IPC_STAT 2 /* Get `ipc_perm' options. */ +#endif /* Special key values. */ #define IPC_PRIVATE ((key_t) 0) /* private key */ diff --git a/sysdeps/gnu/bits/ipc.h b/sysdeps/gnu/bits/ipc.h index 47df305e1c..328c11a0d7 100644 --- a/sysdeps/gnu/bits/ipc.h +++ b/sysdeps/gnu/bits/ipc.h @@ -29,7 +29,11 @@ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* Remove identifier. */ #define IPC_SET 1 /* Set `ipc_perm' options. */ -#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#if __TIMESIZE == 64 && __WORDSIZE == 32 +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ +#else +# define IPC_STAT 2 /* Get `ipc_perm' options. */ +#endif #ifdef __USE_GNU # define IPC_INFO 3 /* See ipcs. */ #endif diff --git a/sysdeps/unix/sysv/linux/bits/ipc.h b/sysdeps/unix/sysv/linux/bits/ipc.h index 085dd628ac..44449de62f 100644 --- a/sysdeps/unix/sysv/linux/bits/ipc.h +++ b/sysdeps/unix/sysv/linux/bits/ipc.h @@ -29,7 +29,11 @@ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* Remove identifier. */ #define IPC_SET 1 /* Set `ipc_perm' options. */ -#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#if __TIMESIZE == 64 && __WORDSIZE == 32 +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ +#else +# define IPC_STAT 2 /* Get `ipc_perm' options. */ +#endif #ifdef __USE_GNU # define IPC_INFO 3 /* See ipcs. */ #endif diff --git a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h index d9d902ed0d..b135301356 100644 --- a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." #endif +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h index 39c0e53f38..3613c5ec94 100644 --- a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." #endif +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h index 1ab16492dd..e26906a67f 100644 --- a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h @@ -20,6 +20,19 @@ # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." #endif +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime; /* last semop time */ + __syscall_ulong_t sem_ctime; /* last change time */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t sem_otime_high; + __syscall_ulong_t sem_ctime_high; +}; +#endif + /* Data structure describing a set of semaphores. */ struct semid_ds { diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h index 79b4cba939..ec2ff552eb 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." #endif +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c index 0c3eb0932f..3ac6d01b84 100644 --- a/sysdeps/unix/sysv/linux/semctl.c +++ b/sysdeps/unix/sysv/linux/semctl.c @@ -23,11 +23,16 @@ #include <shlib-compat.h> #include <errno.h> +#define __IPC_TIME64 (IPC_STAT & __IPC_64) + /* Define a `union semun' suitable for Linux here. */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ +#if __WORDSIZE == 32 + struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */ +#endif unsigned short int *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; @@ -43,13 +48,25 @@ union semun static int semctl_syscall (int semid, int semnum, int cmd, union semun arg) { + int ret; #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, - arg.array); + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, + arg.array); #else - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, - SEMCTL_ARG_ADDRESS (arg)); + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, + SEMCTL_ARG_ADDRESS (arg)); +#endif + +#if __IPC_TIME64 + if (ret == 0 && (cmd & __IPC_TIME64)) + { + arg.buf->sem_ctime = arg.buf32->sem_ctime | + ((time_t) arg.buf32->sem_ctime_high << 32); + arg.buf->sem_otime = arg.buf32->sem_otime | + ((time_t) arg.buf32->sem_otime_high << 32); + } #endif + return ret; } int diff --git a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h index f8de676e79..b08fb8a79e 100644 --- a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." #endif +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h index 42694069d5..c7b9adce88 100644 --- a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead." #endif +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif + /* Data structure describing a set of semaphores. */ struct semid_ds {