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 > { > _______________________________________________ linux-snps-arc mailing list linux-snps-arc@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/linux-snps-arc