From patchwork Sat Feb 24 18:21:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Chestnykh X-Patchwork-Id: 1903861 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=QwLmrLMh; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=uclibc-ng.org (client-ip=2a00:1828:2000:679::23; helo=helium.openadk.org; envelope-from=devel-bounces@uclibc-ng.org; receiver=patchwork.ozlabs.org) Received: from helium.openadk.org (helium.openadk.org [IPv6:2a00:1828:2000:679::23]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ThwFx6xFPz23d2 for ; Sun, 25 Feb 2024 05:22:11 +1100 (AEDT) Received: from helium.openadk.org (localhost [IPv6:::1]) by helium.openadk.org (Postfix) with ESMTP id 0A9A2352860C; Sat, 24 Feb 2024 19:22:03 +0100 (CET) Authentication-Results: helium.openadk.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=QwLmrLMh; dkim-atps=neutral Received: from mail-lj1-f173.google.com (mail-lj1-f173.google.com [209.85.208.173]) by helium.openadk.org (Postfix) with ESMTPS id 9C5783528385 for ; Sat, 24 Feb 2024 19:21:58 +0100 (CET) Received: by mail-lj1-f173.google.com with SMTP id 38308e7fff4ca-2d247f58159so7414361fa.0 for ; Sat, 24 Feb 2024 10:21:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1708798917; x=1709403717; darn=uclibc-ng.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YRSxqjhA8bAWF3XYgLgVPk6K+B2fmONNhCLR4M5vKyI=; b=QwLmrLMhi45jKK4lJNH2dNO1GIN3zsVpXrLVfg03j8qr+D80BkMkt3zl3WcxNXZ8Hd yr2A8uArA7Tydi+lpBBQ7ekHf3Pyi2l/a3F59h7fHOnlFUjpRXSNpWlmUSjF/3WAW/Ce seCQ8FkeCLah0+bLs03siGhOvoqApV5zY/CTmTeMrPTpaTsXZB9fRh4UmPRwML57/9W4 T6287NrdOTwN1wohIbM7/9NJUMAlqPculn9yRjGdNVen9OQxYebTo2ucxpArVLwuXS4h qLQaXEJQcG9N8S6B/wBaUMPw8EjO4AxdPazhWMlbSboDC3ErWPyku64Gzn1t87b80RhK CQrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708798917; x=1709403717; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YRSxqjhA8bAWF3XYgLgVPk6K+B2fmONNhCLR4M5vKyI=; b=IY1U91uDPw3L8ePOQSdgyhqczJw7iYwXS300wCrdIHKNZVawuRhXUfWMPhmseul4lj 3ChRt6MljvkfARodWXKN0IZtNmLn4LCmqdWIo2zJlwF9P0Eep/leDhWlpe+/iGmeair7 kr0R0RgtZ+WmcEe3feK4Md4azwYYl6KQXlazOX8EnaVqU0bW03C5TYzZqex1HBviANZo pzbWHDAwO8AbY2DpmWrTZOqDFx66do5yOI1VYLQfXtRHhxNtrMaQvLfyfaF6XaGrCmtA 096x7v1rkWlwf8Vwow/JgWMWHYs7xZP67P0ZnUy28cs5VkI6g1obwLTa3EQF/jHnR8x1 8NEw== X-Gm-Message-State: AOJu0YyRy6YEUMYP0fCUaTWHfsjJKZ/RtByEASIPBB+N4y8wdNruw6L8 Do2/F1oAurfDgCBYXvxlPcOb11zQe6xYHk6zg7vQsr5FDGteyAZ0hJcrYhkg X-Google-Smtp-Source: AGHT+IHwYoorRLT6pO/yEBBxsLWjYQN0OxGt6eGQpFZFfe9T9wzABpyr4nSVTR5PxItyROs74lYpLQ== X-Received: by 2002:a05:6512:308a:b0:512:ac4c:c91 with SMTP id z10-20020a056512308a00b00512ac4c0c91mr1645264lfd.1.1708798916573; Sat, 24 Feb 2024 10:21:56 -0800 (PST) Received: from localhost.localdomain ([2a00:1370:817a:d2b8:c01f:f888:2e91:e70d]) by smtp.gmail.com with ESMTPSA id e7-20020ac24e07000000b00512ecd552edsm273542lfr.289.2024.02.24.10.21.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 24 Feb 2024 10:21:56 -0800 (PST) From: Dmitry Chestnykh To: devel@uclibc-ng.org Date: Sat, 24 Feb 2024 21:21:39 +0300 Message-ID: <20240224182140.1988000-1-dm.chestnykh@gmail.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: References: MIME-Version: 1.0 Message-ID-Hash: 2X3HYU3QAIPJLBGL6UISTOP5NIME4FAX X-Message-ID-Hash: 2X3HYU3QAIPJLBGL6UISTOP5NIME4FAX X-MailFrom: dm.chestnykh@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Dmitry Chestnykh X-Mailman-Version: 3.3.3 Precedence: list Subject: [uclibc-ng-devel] [PATCH 1/2] Add support for using time64 on big-endian machines. List-Id: uClibc-ng Development Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: For BE architectures there is one significant difference in comparison with time64 support for little-endian architectures like ARMv7. The difference is that we strictly need to pass two 64bit values to system calls because Linux Kernel internally uses `struct __kernel_timespec` and similar, which consists of two 64bit fields. For this reason many files have been changed to convert pointers to timespec-family structures (mixed of 64bit and 32bit values) to the pointer of the similar but 64bit-only structures for using as system calls args. This is general prerequisite for any BE architecture. Signed-off-by: Dmitry Chestnykh --- include/time.h | 27 +++++++++++++++++++ libc/inet/socketcalls.c | 2 +- libc/misc/sysvipc/sem.c | 6 ++++- libc/signal/sigwait.c | 3 ++- libc/sysdeps/linux/common/__rt_sigtimedwait.c | 6 ++--- libc/sysdeps/linux/common/__rt_sigwaitinfo.c | 2 +- libc/sysdeps/linux/common/alarm.c | 2 +- libc/sysdeps/linux/common/clock_getres.c | 13 +++++++-- libc/sysdeps/linux/common/clock_gettime.c | 12 ++++++++- libc/sysdeps/linux/common/clock_settime.c | 5 +++- libc/sysdeps/linux/common/ppoll.c | 2 +- libc/sysdeps/linux/common/pselect.c | 2 +- libc/sysdeps/linux/common/select.c | 12 ++++++--- libc/sysdeps/linux/common/time.c | 2 +- libc/sysdeps/linux/common/timerfd.c | 5 +++- libc/sysdeps/linux/common/utimensat.c | 16 ++++++++++- libpthread/nptl/pthread_mutex_timedlock.c | 2 +- .../sysdeps/unix/sysv/linux/lowlevellock.c | 5 ++-- .../sysdeps/unix/sysv/linux/lowlevellock.h | 27 +++++++++++++++++-- .../unix/sysv/linux/lowlevelrobustlock.c | 1 - .../sysdeps/unix/sysv/linux/timer_settime.c | 2 +- librt/clock_gettime.c | 11 ++++++-- librt/clock_nanosleep.c | 5 ++-- librt/mq_timedreceive.c | 8 +++--- librt/mq_timedsend.c | 6 ++++- librt/timer_settime.c | 9 +++++-- 26 files changed, 154 insertions(+), 39 deletions(-) diff --git a/include/time.h b/include/time.h index 1a1408990..880a80d85 100644 --- a/include/time.h +++ b/include/time.h @@ -122,6 +122,16 @@ struct timespec long int tv_nsec; /* Nanoseconds. */ }; +#if defined(__UCLIBC_USE_TIME64__) + +struct __ts64_struct { + __S64_TYPE tv_sec; + __S64_TYPE tv_nsec; +}; + +#define TO_TS64_P(__ts) (&(struct __ts64_struct) {.tv_sec = (__ts)->tv_sec, .tv_nsec = (__ts)->tv_nsec}) +#endif + #endif /* timespec not defined and or need timespec. */ #undef __need_timespec @@ -165,6 +175,23 @@ struct itimerspec struct timespec it_value; }; +#if defined(__UCLIBC_USE_TIME64__) + +struct __its64_struct { + __S64_TYPE interval_tv_sec; + __S64_TYPE interval_tv_nsec; + __S64_TYPE value_tv_sec; + __S64_TYPE value_tv_nsec; +}; + +#define TO_ITS64_P(__its) (&(struct __its64_struct) {.interval_tv_sec = (__its)->it_interval.tv_sec, \ + .interval_tv_nsec = (__its)->it_interval.tv_nsec, \ + .value_tv_sec = (__its)->it_value.tv_sec, \ + .value_tv_nsec = (__its)->it_value.tv_nsec}) + +#endif + + /* We can use a simple forward declaration. */ struct sigevent; diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c index eb0983698..ea623878a 100644 --- a/libc/inet/socketcalls.c +++ b/libc/inet/socketcalls.c @@ -273,7 +273,7 @@ static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen, int flags, struct timespec *tmo) { # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_recvmmsg_time64) - return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, tmo); + return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, tmo ? TO_TS64_P(tmo) : 0); # elif defined(__NR_recvmmsg) return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen, flags, tmo); # elif __NR_socketcall diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c index cd541761c..48d345984 100644 --- a/libc/misc/sysvipc/sem.c +++ b/libc/misc/sysvipc/sem.c @@ -96,7 +96,11 @@ int semop (int semid, struct sembuf *sops, size_t nsops) #ifdef L_semtimedop #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_semtimedop_time64) -_syscall4_time64(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout) +int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout) +{ + return INLINE_SYSCALL(semtimedop_time64, 4, semid, sops, nsops, timeout ? TO_TS64_P(timeout) : 0); +} + #elif defined(__NR_semtimedop) _syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout) diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c index 3557a039e..b237534cd 100644 --- a/libc/signal/sigwait.c +++ b/libc/signal/sigwait.c @@ -24,7 +24,8 @@ #include #include -#if defined __NR_rt_sigtimedwait && defined __UCLIBC_HAS_REALTIME__ +#if (defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64))) && \ + defined(__UCLIBC_HAS_REALTIME__) #include diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/libc/sysdeps/linux/common/__rt_sigtimedwait.c index bd82ca6d5..44e1ce928 100644 --- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c @@ -9,7 +9,7 @@ #include -#ifdef __NR_rt_sigtimedwait +#if defined(__NR_rt_sigtimedwait) || (defined(__NR_rt_sigtimedwait_time64) && defined(__UCLIBC_USE_TIME64__)) # include # include # ifdef __UCLIBC_HAS_THREADS_NATIVE__ @@ -54,7 +54,7 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info, /* on uClibc we use the kernel sigset_t size */ # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64) result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info, - timeout, __SYSCALL_SIGSET_T_SIZE); + timeout ? TO_TS64_P(timeout) : 0, __SYSCALL_SIGSET_T_SIZE); # else result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info, timeout, __SYSCALL_SIGSET_T_SIZE); @@ -72,7 +72,7 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info, /* on uClibc we use the kernel sigset_t size */ # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64) return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info, - timeout, __SYSCALL_SIGSET_T_SIZE); + timeout ? TO_TS64_P(timeout) : 0, __SYSCALL_SIGSET_T_SIZE); # else return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info, timeout, __SYSCALL_SIGSET_T_SIZE); diff --git a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c index d2d176a64..7830b2e2c 100644 --- a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c +++ b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c @@ -9,7 +9,7 @@ #include -#ifdef __NR_rt_sigtimedwait +#if defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)) # define __need_NULL # include # include diff --git a/libc/sysdeps/linux/common/alarm.c b/libc/sysdeps/linux/common/alarm.c index 4e6e2215b..861f6ad8e 100644 --- a/libc/sysdeps/linux/common/alarm.c +++ b/libc/sysdeps/linux/common/alarm.c @@ -9,7 +9,7 @@ #include #include -#ifdef __NR_alarm && !defined(__UCLIBC_USE_TIME64__) +#if defined(__NR_alarm) && !defined(__UCLIBC_USE_TIME64__) _syscall1(unsigned int, alarm, unsigned int, seconds) #else # include diff --git a/libc/sysdeps/linux/common/clock_getres.c b/libc/sysdeps/linux/common/clock_getres.c index d4b989958..c1818f9ce 100644 --- a/libc/sysdeps/linux/common/clock_getres.c +++ b/libc/sysdeps/linux/common/clock_getres.c @@ -10,9 +10,18 @@ #include #include - #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) -_syscall2_time64(int, clock_getres, clockid_t, clock_id, struct timespec*, res) +int clock_getres(clockid_t clock_id, struct timespec *res) +{ + struct __ts64_struct __ts64; + int __ret = INLINE_SYSCALL(clock_getres_time64, 2, clock_id, &__ts64); + if (__ret == 0 && res) { + res->tv_sec = __ts64.tv_sec; + res->tv_nsec = __ts64.tv_nsec; + }; + + return __ret; +} #elif defined(__NR_clock_getres) _syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res) #else diff --git a/libc/sysdeps/linux/common/clock_gettime.c b/libc/sysdeps/linux/common/clock_gettime.c index a595bd691..00212a9ef 100644 --- a/libc/sysdeps/linux/common/clock_gettime.c +++ b/libc/sysdeps/linux/common/clock_gettime.c @@ -12,7 +12,17 @@ #include #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64) -_syscall2_64(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp) +int clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + struct __ts64_struct __ts64; + int __ret = INLINE_SYSCALL(clock_gettime64, 2, clock_id, &__ts64); + if (tp) { + tp->tv_sec = __ts64.tv_sec; + tp->tv_nsec = __ts64.tv_nsec; + } + + return __ret; +} #elif defined(__NR_clock_gettime) _syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp) #else diff --git a/libc/sysdeps/linux/common/clock_settime.c b/libc/sysdeps/linux/common/clock_settime.c index 89550af5a..666ae4075 100644 --- a/libc/sysdeps/linux/common/clock_settime.c +++ b/libc/sysdeps/linux/common/clock_settime.c @@ -12,7 +12,10 @@ #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64) -_syscall2_64(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp) +int clock_settime(clockid_t clock_id, const struct timespec *tp) +{ + return INLINE_SYSCALL(clock_settime64, 2, clock_id, tp ? TO_TS64_P(tp) : 0); +} #elif defined(__NR_clock_settime) _syscall2(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp) #else diff --git a/libc/sysdeps/linux/common/ppoll.c b/libc/sysdeps/linux/common/ppoll.c index cb36149c5..3b98a2760 100644 --- a/libc/sysdeps/linux/common/ppoll.c +++ b/libc/sysdeps/linux/common/ppoll.c @@ -38,7 +38,7 @@ __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, timeout = &tval; } #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_ppoll_time64) - return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE); + return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout ? TO_TS64_P(timeout) : 0, sigmask, __SYSCALL_SIGSET_T_SIZE); #else return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE); #endif diff --git a/libc/sysdeps/linux/common/pselect.c b/libc/sysdeps/linux/common/pselect.c index 23bdab5cf..3ceb51012 100644 --- a/libc/sysdeps/linux/common/pselect.c +++ b/libc/sysdeps/linux/common/pselect.c @@ -57,7 +57,7 @@ static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds, sigmask = (void *)&data; } #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64) - return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask); + return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, timeout ? TO_TS64_P(timeout) : 0, sigmask); #else return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask); #endif diff --git a/libc/sysdeps/linux/common/select.c b/libc/sysdeps/linux/common/select.c index 3132a109c..05d2b55b2 100644 --- a/libc/sysdeps/linux/common/select.c +++ b/libc/sysdeps/linux/common/select.c @@ -15,7 +15,7 @@ # define __NR_select __NR__newselect #endif -#if !defined __NR_select && defined __NR_pselect6 +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64) # include # define USEC_PER_SEC 1000000L #endif @@ -23,9 +23,7 @@ int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { -#ifdef __NR_select - return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, timeout); -#elif defined __NR_pselect6 +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64) struct timespec _ts, *ts = 0; if (timeout) { uint32_t usec; @@ -47,8 +45,14 @@ int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, ts = &_ts; } +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64) + return INLINE_SYSCALL(pselect6_time64, 6, n, readfds, writefds, exceptfds, ts ? TO_TS64_P(ts) : 0, 0); +#else return INLINE_SYSCALL(pselect6, 6, n, readfds, writefds, exceptfds, ts, 0); #endif +#elif defined(__NR_select) + return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, ts); +#endif } /* we should guard it, but we need it in other files, so let it fail * if we miss any of the syscalls */ diff --git a/libc/sysdeps/linux/common/time.c b/libc/sysdeps/linux/common/time.c index 22403f174..d084ffaad 100644 --- a/libc/sysdeps/linux/common/time.c +++ b/libc/sysdeps/linux/common/time.c @@ -9,7 +9,7 @@ #include #include -#ifdef __NR_time +#if defined(__NR_time) && !defined(__UCLIBC_USE_TIME64__) _syscall_noerr1(time_t, time, time_t *, t) #else # include diff --git a/libc/sysdeps/linux/common/timerfd.c b/libc/sysdeps/linux/common/timerfd.c index 0f19b44ed..07bfb09b7 100644 --- a/libc/sysdeps/linux/common/timerfd.c +++ b/libc/sysdeps/linux/common/timerfd.c @@ -21,7 +21,10 @@ _syscall2(int, timerfd_create, int, clockid, int, flags) */ #if defined(__NR_timerfd_settime) || defined(__NR_timerfd_settime64) #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_settime64) -_syscall4_64(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) +int timerfd_settime(int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) +{ + return INLINE_SYSCALL(timerfd_settime64, 4, ufd, flags, utmr ? TO_ITS64_P(utmr) : 0, otmr); +} #else _syscall4(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) #endif diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c index 6a78ebb4f..339a35559 100644 --- a/libc/sysdeps/linux/common/utimensat.c +++ b/libc/sysdeps/linux/common/utimensat.c @@ -11,7 +11,21 @@ #if defined(__NR_utimensat) || defined(__NR_utimensat_time64) #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_utimensat_time64) -_syscall4_time64(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags) +int utimensat(int fd, const char *path, const struct timespec times[2], int flags) +{ + struct __ts64_struct __times64[2] = { + { + .tv_sec = times ? times[0].tv_sec : 0, + .tv_nsec = times ? times[0].tv_nsec : 0 + }, + { + .tv_sec = times ? times[1].tv_sec : 0, + .tv_nsec = times ? times[1].tv_nsec : 0 + } + }; + + return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ? &__times64 : 0, flags); +} #else _syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags) #endif diff --git a/libpthread/nptl/pthread_mutex_timedlock.c b/libpthread/nptl/pthread_mutex_timedlock.c index 25f9ec3b2..7bb9a0aaf 100644 --- a/libpthread/nptl/pthread_mutex_timedlock.c +++ b/libpthread/nptl/pthread_mutex_timedlock.c @@ -268,7 +268,7 @@ pthread_mutex_timedlock ( int e = INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_LOCK_PI, private), 1, - abstime); + abstime ? TO_TS64_P(abstime) : 0); #else int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_LOCK_PI, diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c index 4294a20b0..e168b3925 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c @@ -95,7 +95,7 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime) while ((tid = *tidp) != 0) { struct timeval tv; - struct timespec rt; + struct timespec rt, *rtp; /* Get the current time. */ (void) __gettimeofday (&tv, NULL); @@ -115,7 +115,8 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime) /* Wait until thread terminates. The kernel so far does not use the private futex operations for this. */ - if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + rtp = &rt; + if (lll_futex_timed_wait (tidp, tid, rtp, LLL_SHARED) == -ETIMEDOUT) return ETIMEDOUT; } diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h index e72fe5234..909b0aad3 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h @@ -71,8 +71,31 @@ # endif #endif +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + #define lll_futex_wait(futexp, val, private) \ - lll_futex_timed_wait(futexp, val, NULL, private) + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), NULL); \ + __ret; \ + }) + +#else + +#define lll_futex_wait(futexp, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), NULL); \ + __ret; \ + }) + +#endif #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) @@ -82,7 +105,7 @@ long int __ret; \ __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp), \ __lll_private_flag (FUTEX_WAIT, private), \ - (val), (timespec)); \ + (val), (TO_TS64_P(timespec))); \ __ret; \ }) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c index 7b4e84343..6403f7ea0 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c @@ -99,7 +99,6 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime, if (oldval != newval && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) continue; - lll_futex_timed_wait (futex, newval, &rt, private); try: diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c index 80d242f21..4fa600cb6 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c @@ -56,7 +56,7 @@ timer_settime ( /* Delete the kernel timer object. */ # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64) int res = INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags, - value, ovalue); + value ? TO_ITS64_P(value) : 0, ovalue); # else int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags, value, ovalue); diff --git a/librt/clock_gettime.c b/librt/clock_gettime.c index b66b60231..c514e1a54 100644 --- a/librt/clock_gettime.c +++ b/librt/clock_gettime.c @@ -24,8 +24,15 @@ #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64) #define SYSCALL_GETTIME \ - retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \ - break + { \ + struct __ts64_struct __ts64; \ + retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, &__ts64); \ + if (tp) { \ + tp->tv_sec = __ts64.tv_sec; \ + tp->tv_nsec = __ts64.tv_nsec; \ + } \ + break; \ + } #else #define SYSCALL_GETTIME \ retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \ diff --git a/librt/clock_nanosleep.c b/librt/clock_nanosleep.c index eaae75720..cb7b2afa3 100644 --- a/librt/clock_nanosleep.c +++ b/librt/clock_nanosleep.c @@ -21,7 +21,6 @@ #include "kernel-posix-cpu-timers.h" - /* We can simply use the syscall. The CPU clocks are not supported with this function. */ int @@ -38,7 +37,7 @@ clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, if (SINGLE_THREAD_P) #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64) - r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem); + r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req ? TO_TS64_P(req) : 0, rem); #else r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem); #endif @@ -47,7 +46,7 @@ clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, #ifdef __NEW_THREADS int oldstate = LIBC_CANCEL_ASYNC (); #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64) - r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem); + r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req ? TO_TS64_P(req): 0, rem); #else r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem); diff --git a/librt/mq_timedreceive.c b/librt/mq_timedreceive.c index db1ae1aa8..2570b6f9e 100644 --- a/librt/mq_timedreceive.c +++ b/librt/mq_timedreceive.c @@ -9,12 +9,14 @@ #include #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedreceive_time64) -#define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive_time64 +int _NC(mq_timedreceive)(mqd_t mqdes, char *restrict msg_ptr, size_t msg_len, unsigned int *restrict msq_prio, const struct timespec *restrict abs_timeout) +{ + return INLINE_SYSCALL(mq_timedreceive_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, abs_timeout ? TO_TS64_P(abs_timeout) : 0); +} #else #define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive -#endif - _syscall5(ssize_t, __NC(mq_timedreceive), mqd_t, mqdes, char *__restrict, msg_ptr, size_t, msg_len, unsigned int *__restrict, msq_prio, const struct timespec *__restrict, abs_timeout) +#endif CANCELLABLE_SYSCALL(ssize_t, mq_timedreceive, (mqd_t mqdes, char *__restrict msg_ptr, size_t msq_len, unsigned int *__restrict msq_prio, const struct timespec *__restrict abs_timeout), (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout)) diff --git a/librt/mq_timedsend.c b/librt/mq_timedsend.c index 6afaf5157..bcbc0685f 100644 --- a/librt/mq_timedsend.c +++ b/librt/mq_timedsend.c @@ -10,11 +10,15 @@ #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedsend_time64) #define __NR___mq_timedsend_nocancel __NR_mq_timedsend_time64 +int _NC(mq_timedsend)(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msq_prio, const struct timespec *abs_timeout) +{ + return INLINE_SYSCALL(mq_timedsend_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, abs_timeout ? TO_TS64_P(abs_timeout) : 0); +} #else #define __NR___mq_timedsend_nocancel __NR_mq_timedsend +_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout) #endif -_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout) CANCELLABLE_SYSCALL(int, mq_timedsend, (mqd_t mqdes, const char *msg_ptr, size_t msq_len, unsigned int msq_prio, const struct timespec *abs_timeout), (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout)) lt_libc_hidden(mq_timedsend) diff --git a/librt/timer_settime.c b/librt/timer_settime.c index 022880297..6bf5f8307 100644 --- a/librt/timer_settime.c +++ b/librt/timer_settime.c @@ -12,10 +12,14 @@ #if defined(__NR_timer_settime) || defined(__NR_timer_settime64) #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64) -#define __NR___syscall_timer_settime __NR_timer_settime64 +int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue) +{ + struct timer *kt = (struct timer *)timerid; + + return INLINE_SYSCALL(timer_settime64, 4, kt->ktimerid, flags, value ? TO_ITS64_P(value) : 0, ovalue); +} #else #define __NR___syscall_timer_settime __NR_timer_settime -#endif static __inline__ _syscall4(int, __syscall_timer_settime, kernel_timer_t, ktimerid, int, flags, const void *, value, void *, ovalue); @@ -31,3 +35,4 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, } #endif +#endif From patchwork Sat Feb 24 18:21:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Chestnykh X-Patchwork-Id: 1903862 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=Ik8Ho4VB; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=uclibc-ng.org (client-ip=89.238.66.15; helo=helium.openadk.org; envelope-from=devel-bounces@uclibc-ng.org; receiver=patchwork.ozlabs.org) Received: from helium.openadk.org (helium.openadk.org [89.238.66.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4ThwG13QkRz23d2 for ; Sun, 25 Feb 2024 05:22:17 +1100 (AEDT) Received: from helium.openadk.org (localhost [IPv6:::1]) by helium.openadk.org (Postfix) with ESMTP id 2EA48352860D; Sat, 24 Feb 2024 19:22:11 +0100 (CET) Authentication-Results: helium.openadk.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=Ik8Ho4VB; dkim-atps=neutral Received: from mail-lf1-f44.google.com (mail-lf1-f44.google.com [209.85.167.44]) by helium.openadk.org (Postfix) with ESMTPS id EC72935285F3 for ; Sat, 24 Feb 2024 19:22:00 +0100 (CET) Received: by mail-lf1-f44.google.com with SMTP id 2adb3069b0e04-512f71b7cbbso35945e87.0 for ; Sat, 24 Feb 2024 10:22:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1708798920; x=1709403720; darn=uclibc-ng.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9ehBxWCcCKaNO4oSjiNjiU6PCuTvDRW9VrYGGYebXyE=; b=Ik8Ho4VB5/NveJmAtP89W6hy9geWi9gXuXYpIkdRKF7aSR2zv1hRt3Sg+mrW798om+ fvHM2BMUeaIWRaOFo4SHSxh/a9JXdLUh7q2wryzyB9VxDIbhlM3qo7smU+G8RZ4jjEF3 xJ/p5/O8np/g6XzmXl6YGoVVDjvMvpfmYJYQsZOJHzbfgyXp1d96Kow91tO1Dpku0AH2 Jo3cFd5/Nj7i6NW1avTm9MSIlVJWOO1V0A2CEFyxMF2jBLaCge2mujOk5KE5HpG8OmqD d8hVm6vz9uuzZuGAf7/r2EsSgDB+o/rpW2b5nxiCcVNXuRwiDl1cCmAr6pQHJNNa7ZPS M5Vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708798920; x=1709403720; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9ehBxWCcCKaNO4oSjiNjiU6PCuTvDRW9VrYGGYebXyE=; b=KilyzlctngSXkNdR42UJ3414P10FH9EdXTMffUVvsGxIv7lm+eIs7ZAOGrdfyOOIsz tzXIl4A4SVppSHqmObwH0vlqtWDT9odXxB8u47G/RAWFnDnhpDbjySp3BYAVlYIOBtGn vnVS10lfU3fhxv4Z3xSJC6jjYfKPCRizw8qUIxxvv/0aocYcqiiGKVH2Z5hZNIMNna/x 1MwQyHF340uTnu4HFZxFG5+AXVvwKx5uJlulpQq2A2RKRSuilk651hLRPbL9JRkgiQla +wF+QAjKNg4xazRTWfHo2GZSps9LPYV+E2Wf/bcR82HHxLQAm6aQEpcPyOGK7UAslZJc GzDw== X-Gm-Message-State: AOJu0YwLKoqUO39EVTKqNpOY94XPoLvq6Td342yyxGBe26bYviNZVtT4 jffcDEUn/7Bqk03mhGJZdteHEl34o+roJ620LDSjQoONvGEV92B7bqQNUQiK X-Google-Smtp-Source: AGHT+IGVWX+HZln0/+Lq2Y9zLGbifE2m+zVJrmIbb+z1F1SXYhayegQXlrEyuRxIdlGy+ypXIYYW7A== X-Received: by 2002:a19:8c42:0:b0:512:bead:a28d with SMTP id i2-20020a198c42000000b00512beada28dmr1377650lfj.5.1708798919586; Sat, 24 Feb 2024 10:21:59 -0800 (PST) Received: from localhost.localdomain ([2a00:1370:817a:d2b8:c01f:f888:2e91:e70d]) by smtp.gmail.com with ESMTPSA id e7-20020ac24e07000000b00512ecd552edsm273542lfr.289.2024.02.24.10.21.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 24 Feb 2024 10:21:59 -0800 (PST) From: Dmitry Chestnykh To: devel@uclibc-ng.org Date: Sat, 24 Feb 2024 21:21:40 +0300 Message-ID: <20240224182140.1988000-2-dm.chestnykh@gmail.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240224182140.1988000-1-dm.chestnykh@gmail.com> References: <20240224182140.1988000-1-dm.chestnykh@gmail.com> MIME-Version: 1.0 Message-ID-Hash: JFVSKTBC24NAAPYRHRI74KOJDBCWNTSX X-Message-ID-Hash: JFVSKTBC24NAAPYRHRI74KOJDBCWNTSX X-MailFrom: dm.chestnykh@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Dmitry Chestnykh X-Mailman-Version: 3.3.3 Precedence: list Subject: [uclibc-ng-devel] [PATCH 2/2] Add time64 support for PowerPC. List-Id: uClibc-ng Development Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Signed-off-by: Dmitry Chestnykh --- extra/Configs/Config.in | 2 +- libc/sysdeps/linux/powerpc/bits/kernel_stat.h | 28 +++++++++++++++++-- libc/sysdeps/linux/powerpc/bits/sem.h | 16 +++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index 9351dffc8..f11a63b79 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -1026,7 +1026,7 @@ config UCLIBC_FALLBACK_TO_ETC_LOCALTIME config UCLIBC_USE_TIME64 bool "Use *time64 syscalls instead of 32bit ones (if possible)" - depends on TARGET_arm || TARGET_xtensa + depends on TARGET_arm || TARGET_powerpc || TARGET_xtensa # TODO: add support for other architectures default n diff --git a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h index ce62b2ba2..0e76120ab 100644 --- a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h +++ b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h @@ -5,6 +5,16 @@ * struct kernel_stat should look like... It turns out each arch has a * different opinion on the subject... */ +#if defined(__UCLIBC_USE_TIME64__) +#include + +struct ts32_struct { + __S32_TYPE tv_sec; + __S32_TYPE tv_nsec; +}; + +#endif + #if __WORDSIZE == 64 #define kernel_stat kernel_stat64 #else @@ -19,9 +29,15 @@ struct kernel_stat { __kernel_off_t st_size; unsigned long st_blksize; unsigned long st_blocks; +#if defined(__UCLIBC_USE_TIME64__) + struct ts32_struct __st_atim32; + struct ts32_struct __st_mtim32; + struct ts32_struct __st_ctim32; +#else struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; +#endif unsigned long __unused4; unsigned long __unused5; }; @@ -39,9 +55,15 @@ struct kernel_stat64 { long long st_size; /* Size of file, in bytes. */ long st_blksize; /* Optimal block size for I/O. */ long long st_blocks; /* Number 512-byte blocks allocated. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ +#if defined(__UCLIBC_USE_TIME64__) + struct ts32_struct __st_atim32; + struct ts32_struct __st_mtim32; + struct ts32_struct __st_ctim32; +#else + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +#endif unsigned long int __uclibc_unused4; unsigned long int __uclibc_unused5; }; diff --git a/libc/sysdeps/linux/powerpc/bits/sem.h b/libc/sysdeps/linux/powerpc/bits/sem.h index a9d895374..8d338eac0 100644 --- a/libc/sysdeps/linux/powerpc/bits/sem.h +++ b/libc/sysdeps/linux/powerpc/bits/sem.h @@ -35,6 +35,7 @@ #define SETALL 17 /* set all semval's */ + /* Data structure describing a set of semaphores. */ struct semid_ds { @@ -42,16 +43,31 @@ struct semid_ds #if __WORDSIZE == 32 unsigned int __uclibc_unused1; #endif +#if defined(__UCLIBC_USE_TIME64__) + unsigned long int __sem_otime_internal_1; /* last semop() time */ + unsigned long int __sem_otime_internal_2; +#else __time_t sem_otime; /* last semop() time */ +#endif #if __WORDSIZE == 32 unsigned int __uclibc_unused2; #endif +#if defined(__UCLIBC_USE_TIME64__) + unsigned long int __sem_ctime_internal_1; /* last time changed by semctl() */ + unsigned long int __sem_ctime_internal_2; +#else __time_t sem_ctime; /* last time changed by semctl() */ +#endif unsigned long int sem_nsems; /* number of semaphores in set */ +#if defined(__UCLIBC_USE_TIME64__) + __time_t sem_otime; + __time_t sem_ctime; +#endif unsigned long __uclibc_unused3; unsigned long __uclibc_unused4; }; + /* The user should define a union like the following to use it for arguments for `semctl'.