From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qv1-xf42.google.com (mail-qv1-xf42.google.com [IPv6:2607:f8b0:4864:20::f42]) by sourceware.org (Postfix) with ESMTPS id AB896385DC26 for ; Thu, 30 Apr 2020 15:06:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AB896385DC26 Received: by mail-qv1-xf42.google.com with SMTP id t8so3133256qvw.5 for ; Thu, 30 Apr 2020 08:06:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:cc:references:from:autocrypt:subject :message-id:date:user-agent:mime-version:in-reply-to :content-language:content-transfer-encoding; bh=JY76aNDRTbthy3kB04AVHuIixnWzjRKTGDy5OeY8RZU=; b=JcnlJYMRZiH4TQIyCpVvR7VmDLee1B7Y8jRuqKGT5ayTrnV1OydJeW5eWw49/udqVA sraWycEVq2jtJTq2RRCaQ0uuPSTaw8MG0tywhghdZDgR60KZlkB0gd2Tvx4m7H6YMD3P 3j2vVHh/6OBROkIoj3+XL4pbGkBtzsUVXcaNm4appz7dE7quSlFoD0sr3wVxpZqKm+sR pG7cQgCNJBDAvWuI4Z3HUEwyzZTSLG3N4Q40XdBHcHkxR578A2Ogu5Qi42pBpp9QSYwb APU1ZDC5tUctbgMqTgoyt3G6D/eXg23G0S5lD/nksyoI73cQovujR0tVYYDRW0HSq50g +a+w== X-Gm-Message-State: AGi0PuZiCa07AsNytQHKt1uO9OvbRbZGm4KmhCt6P5wvm/8ZSY6HBuax FtwRdPp9qfK8+/1/0CD9pyePDw== X-Google-Smtp-Source: APiQypKhZXgMeMag3I8aTk8H73wOhXwwpdBNGjj9Oh8aDT8qunqsztT2JNsd5npRLFUSAaiWRdZeGA== X-Received: by 2002:a05:6214:3ad:: with SMTP id m13mr3405988qvy.57.1588259184760; Thu, 30 Apr 2020 08:06:24 -0700 (PDT) Received: from [192.168.1.4] ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id b10sm217450qkl.19.2020.04.30.08.06.22 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 30 Apr 2020 08:06:23 -0700 (PDT) To: Alistair Francis Cc: GNU C Library , Alistair Francis , Arnd Bergmann References: <20200428220507.3409362-1-alistair.francis@wdc.com> <20200428220507.3409362-4-alistair.francis@wdc.com> <3bec18bd-cbee-5853-2d36-df377b6cf7cf@linaro.org> From: Adhemerval Zanella Autocrypt: addr=adhemerval.zanella@linaro.org; prefer-encrypt=mutual; keydata= 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 Subject: Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Message-ID: <8b082c6c-a025-233f-a396-120349f02d38@linaro.org> Date: Thu, 30 Apr 2020 12:06:20 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-25.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Apr 2020 15:06:36 -0000 On 29/04/2020 20:24, Alistair Francis wrote: > On Wed, Apr 29, 2020 at 2:09 PM Adhemerval Zanella > wrote: >> >> >> >> On 28/04/2020 19:05, Alistair Francis via Libc-alpha 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. >>> >>> Due to alignment differences between 64-bit and 32-bit variables we >>> also need to set nsems to ensure it's correct. >> >> I think this approach might trigger an issue on semid_ds definition for >> time64 that I only noticed now. >> >> Since the idea of semctl is not use a different entrypoint neither to add >> aditional flag when issuing the syscall (either semctl or ipc), with this >> change we need to assure that __TIMESIZE == 32 sem_otime alignment matches >> __TIMESIZE == 64 one. > > I don't follow. We don't assume that sem_otime has the same allignment > for __TIMESIZE == 32 and 64. In fact for RV32 they are not alligned > the same. > >> >> However for semid_ds and msqid_ds time_t members can't not properly aligned >> to be expanded to 64-bit (shmid_ds has a shm_segsz field before the >> timestamp fields) due to the ipc_perm header consisting of 9 32-bit words >> except on parisc/powerpc/sparc. The alignment difference will make >> semctl once programs states build against a semid_ds with time_t >> being an 64-bit type. > > I am missing something here as well, as that is exactly what RV32 is > testing and the glibc tests are passing (and a LInux rootFS boots). The issue is for architectures that might select the __TIMESIZE at build time, so two different semid_ds structure might be used with semctl. For instance, on arm with current scheme: For __TIMESIZE == 32: sizeof (struct ipc_perm): 36 sizeof (struct semid_ds): 72 offsetof (struct semid_ds, sem_perm): 0 offsetof (struct semid_ds, sem_otime): 40 offsetof (struct semid_ds, sem_ctime): 48 offsetof (struct semid_ds, sem_nsems): 56 For __TIMESIZE == 64: sizeof (struct ipc_perm): 36 sizeof (struct semid_ds): 64 offsetof (struct semid_ds, sem_perm): 0 offsetof (struct semid_ds, sem_otime): 36 offsetof (struct semid_ds, sem_ctime): 44 offsetof (struct semid_ds, sem_nsems): 52 The syscall itself will use the expected structure, however the code: if (ret >= 0 && restore) { arg.buf = orig; arg.buf->sem_perm = tmp.sem_perm; arg.buf->sem_otime = tmp.sem_otime | ((time_t) tmp.sem_otime_high << 32); arg.buf->sem_ctime = tmp.sem_ctime | ((time_t) tmp.sem_ctime_high << 32); arg.buf->sem_nsems = tmp.sem_nsems; will write down the timestamps on wrong place for time64 timestamps. This is not an issue for 32-bit architectures that does not have support for 32-bit time_t (as RV32). > >> >> So we have 2 options here: >> >> 1. Keep the semid_ds layout as the kernel expected one and add the >> newer time64 timestamps at the *end*, and redefine the command >> arguments that passes a struct semid_ds to use >> (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds >> is a time64 one. The IPC_64 bit might be a feasible hack since >> kernel won't use on possible new commands. This solution would require to redefine IPC_STAT, SEM_STAT, SEM_STAT_ANY to a different value for when building for __TIMESIZE==64 on ABIs that support its selection. The easiest way would to parametrize the ipc commands that handle per architecture: /* On each ABI that supports __TIMESIZE==32. */ #if __TIMESIZE == 64 # define __IPC_CMD_TIME_64 0x100 /* Same as __IPC_64. */ #else # define __IPC_CMD_TIME_64 0x0 #endif #define __IPC_TIME_64 1 If fro architecture only support __TIMESIZE64 (default): #define __IPC_CMD_TIME64 0x0 #define __IPC_TIME_64 0 Then on Linux ipc.h: #define IPC_STAT (2 | __IPC_CMD_TIME_64) Same for sem.h: #define SEM_STAT (18 | __IPC_CMD_TIME_64) #define SEM_STAT_ANY (20 | __IPC_CMD_TIME_64) Then on semctl.c (totally untested): --- union semun { int val; /* value for SETVAL */ #if __IPC_TIME_64 struct __semid_ds32 *buf32; #endif struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ unsigned short int *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; int __new_semctl (int semid, int semnum, int cmd, ...) { /* POSIX states ipc_perm mode should have type of mode_t. */ _Static_assert (sizeof ((struct semid_ds){0}.sem_perm.mode) == sizeof (mode_t), "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)"); union semun arg = { 0 }; va_list ap; /* Get the argument only if required. Ignore the __IPC_STAT_64. */ switch (cmd & ~__IPC_CMD_TIME_64) { case SETVAL: /* arg.val */ case GETALL: /* arg.array */ case SETALL: case IPC_STAT & ~__IPC_CMD_TIME_64: /* arg.buf */ case IPC_SET: case SEM_STAT & ~__IPC_CMD_TIME_64: case IPC_INFO: /* arg.__buf */ case SEM_INFO: va_start (ap, cmd); arg = va_arg (ap, union semun); va_end (ap); break; } #ifdef __IPC_TIME_64 struct __semid_ds32 tmp32; struct __semid_ds64 *orig64; if (cmd & __IPC_STAT_64) { tmp32 = (struct __semid_ds32) { 0 }; orig64 = (struct __semid_ds64 *) arg.buf; arg.buf32 = tmp32; } #endif #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T struct semid_ds tmpds; if (cmd == IPC_SET) { tmpds = *arg.buf; tmpds.sem_perm.mode *= 0x10000U; arg.buf = &tmpds; } #endif int ret = semctl_syscall (semid, semnum, cmd & ~__IPC_CMD_TIME_64, arg); if (ret < 0) return ret; switch (cmd & ~__IPC_CMD_TIME_64) { case IPC_STAT: case SEM_STAT: case SEM_STAT_ANY: #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T # if __IPC_TIME_64 arg.buf32->sem_perm.mode >>= 16; # else arg.buf->sem_perm.mode >>= 16; # endif #else /* Old Linux kernel versions might not clear the mode padding. */ if (sizeof ((struct semid_ds){0}.sem_perm.mode) ! = sizeof (__kernel_mode_t)) # if __IPC_TIME_64 arg.buf32->sem_perm.mode &= 0xFFFF; # else arg.buf->sem_perm.mode &= 0xFFFF; # endif #endif } #ifdef __IPC_TIME_64 if (cmd & & ~__IPC_CMD_TIME_64) { orig64->sem_perm = tmp32.sem_perm; orig64->sem_otime = tmp32.sem_otime | ((__time64_t) tmp32.sem_otime_high << 32); orig64->sem_ctime = tmp32.sem_ctime | ((__time64_t) tmp32.sem_ctime_high << 32); orig64->sem_nsems = tmp32.sem_nsems; arg.buf = (struct semid_ds *) orig64; } #endif return ret; } --- So basically: 1. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with IPC_STAT without _IPC_CMD_TIME_64, the provided semid_ds buffe will be used directly on the syscall. This is the case for 64-bit architectures and 32-bit architecture without __TIMESIZE==32 support (RV32 for instance). 2. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with IPC_STAT with _IPC_CMD_TIME_64 then __TIMESIZE==64 is implied. A temporary __semid_ds32 will be used to issue the syscall and its contents will be copied to users semid_ds buffer (which is also implied to be the __TIMESIZE==64). There is the requeriment to use define __semid_ds64 that uses __time64_t explicitly for architecture that support __TIMESIZE==32. (The handling of __ASSUME_SYSVIPC_BROKEN_MODE_T and the kernel issue regarding sem_perm.mode clearing could be improved/simplified). >> >> 2. Add a new semctl64 to handle the time64 one semid_ds. >> >>> --- >>> .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++ >>> .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++ >>> .../sysv/linux/powerpc/struct__semid_ds32.h | 32 +++++++++++++ >>> sysdeps/unix/sysv/linux/semctl.c | 47 +++++++++++++++++-- >>> .../sysv/linux/sparc/struct__semid_ds32.h | 32 +++++++++++++ >>> sysdeps/unix/sysv/linux/struct__semid_ds32.h | 32 +++++++++++++ >>> .../unix/sysv/linux/x86/struct__semid_ds32.h | 32 +++++++++++++ >>> 7 files changed, 233 insertions(+), 4 deletions(-) >>> create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h >>> >>> diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..9eceaaff2d >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* HPPA implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-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 >>> + . */ >>> + >>> +#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 >> >> No need to define it for __WORDSIZE == 32, the ABI just supports it >> anyway. > > Ok, I have removed these. > >> >>> diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..2e3e2fc562 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h >>> @@ -0,0 +1,30 @@ >>> +/* MIPS implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-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 >>> + . */ >>> + >>> +#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 >> >> Ok, it cover mips64-n32 as well. >> >>> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..f509db5a02 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* PowerPC implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-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 >>> + . */ >>> + >>> +#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 >> >> Ok. >> >>> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c >>> index 30571af49f..0634cc1abe 100644 >>> --- a/sysdeps/unix/sysv/linux/semctl.c >>> +++ b/sysdeps/unix/sysv/linux/semctl.c >>> @@ -22,8 +22,13 @@ >>> #include >>> #include >>> #include >>> +#include >>> #include /* For __kernel_mode_t. */ >>> >>> +#define IPC_TIME64 \ >>> + (__WORDSIZE == 32 && __TIMESIZE == 64 \ >>> + && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) >> >> I think it would be better to move this definition to the common >> ipc_priv.h header since it will most likely be used on msgctl >> and shmctl y2038 support as well. > > Done. > >> >>> + >>> /* Define a `union semun' suitable for Linux here. */ >>> union semun >>> { >>> @@ -44,13 +49,47 @@ union semun >>> static int >>> semctl_syscall (int semid, int semnum, int cmd, union semun arg) >>> { >>> + int ret; >>> +#if IPC_TIME64 >> >> I think we shoul add a comment stating why we need a auxiliary buffer >> for STAT/STAT_ANY operations. Something like: >> >> A temporary buffer is used to avoid both an issue where the export >> semid_ds might not have follow kernel expected layout (due >> sem_{o,c}time alignment in 64-bit time case) and the issue where >> some kernel version might not clear the high bits when returning >> then sem_{o,c}time information. > > Added > >> >>> + struct __semid_ds32 tmp; >>> + struct semid_ds *orig; >>> + bool restore = false; >>> + if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY) >>> + { >>> + tmp = (struct __semid_ds32) { >>> + .sem_perm = arg.buf->sem_perm, >>> + .sem_otime = arg.buf->sem_otime, >>> + .sem_ctime = arg.buf->sem_ctime, >>> + .sem_nsems = arg.buf->sem_nsems, >>> + }; >> >> We need to fully initialize the temporary struct to avoid a kernel >> issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where >> kernel does not clear the timestamps high bits. > > Added. > >> >>> + orig = arg.buf; >>> + arg.buf = (struct semid_ds*)&tmp; >> >> Space before &tmp. > > Added. > >> >>> + restore = true; >>> + } >>> +#endif >>> + >>> #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS >>> - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, >>> - arg.array); >>> + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, >>> + arg.array); >>> #else >>> - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, >>> - SEMCTL_ARG_ADDRESS (arg)); >>> + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, >>> + SEMCTL_ARG_ADDRESS (arg)); >>> #endif >> >> Ok. >> >>> + >>> +#if IPC_TIME64 >>> + if (ret >= 0 && restore) >>> + { >>> + arg.buf = orig; >>> + arg.buf->sem_perm = tmp.sem_perm; >>> + arg.buf->sem_otime = tmp.sem_otime >>> + | ((time_t) tmp.sem_otime_high << 32); >>> + arg.buf->sem_ctime = tmp.sem_ctime >>> + | ((time_t) tmp.sem_ctime_high << 32); >>> + arg.buf->sem_nsems = tmp.sem_nsems; >> >> I think it would be better to use __time64_t explicit here. > > Done. > > Alistair > >> >>> + } >>> +#endif >>> + >>> + return ret; >>> } >>> >>> int >>> diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..f641825d37 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* Sparc implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-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 >>> + . */ >>> + >>> +#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 >> >> Ok. >> >>> diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..51ff83206d >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* Generic implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-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 >>> + . */ >>> + >>> +#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 >> >> Ok. >> >>> diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..f65c9fc877 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* x86 implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-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 >>> + . */ >>> + >>> +#ifdef __i386__ >>> +/* 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 >>> >> >> Ok. >> >>