linux-user: refactor ipc syscall and support of semtimedop syscall
Refactoring ipc syscall for s390x and SPARC, so it matches glibc implementation
We should add support of semtimedop syscall as new version of glibc
2.31 uses semop based on semtimedop
(commit: 765cdd0bff
).
Signed-off-by: Matus Kysel <mkysel@tachyum.com>
Message-Id: <20200626124612.58593-2-mkysel@tachyum.com>
Message-Id: <20200626124612.58593-3-mkysel@tachyum.com>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
[lv: merged PATCH 1 & 2 to avoid build break on PATCH 1]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
71e2443e4c
commit
d8c08b1e6c
@ -817,9 +817,14 @@ safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
|
||||
const struct timespec *, req, struct timespec *, rem)
|
||||
#endif
|
||||
#ifdef __NR_ipc
|
||||
#ifdef __s390x__
|
||||
safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
|
||||
void *, ptr)
|
||||
#else
|
||||
safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
|
||||
void *, ptr, long, fifth)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __NR_msgsnd
|
||||
safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
|
||||
int, flags)
|
||||
@ -1230,7 +1235,8 @@ static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
|
||||
defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
|
||||
defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
|
||||
defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
|
||||
defined(TARGET_NR_mq_timedreceive)
|
||||
defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
|
||||
defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop)
|
||||
static inline abi_long target_to_host_timespec(struct timespec *host_ts,
|
||||
abi_ulong target_addr)
|
||||
{
|
||||
@ -3878,25 +3884,53 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
|
||||
#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
|
||||
defined(TARGET_NR_semtimedop)
|
||||
|
||||
/*
|
||||
* This macro is required to handle the s390 variants, which passes the
|
||||
* arguments in a different order than default.
|
||||
*/
|
||||
#ifdef __s390x__
|
||||
#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
|
||||
(__nsops), (__timeout), (__sops)
|
||||
#else
|
||||
#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
|
||||
(__nsops), 0, (__sops), (__timeout)
|
||||
#endif
|
||||
|
||||
static inline abi_long do_semtimedop(int semid,
|
||||
abi_long ptr,
|
||||
unsigned nsops,
|
||||
abi_long timeout)
|
||||
{
|
||||
struct sembuf sops[nsops];
|
||||
struct timespec ts, *pts = NULL;
|
||||
abi_long ret;
|
||||
|
||||
if (timeout) {
|
||||
pts = &ts;
|
||||
if (target_to_host_timespec(pts, timeout)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
if (target_to_host_sembuf(sops, ptr, nsops))
|
||||
return -TARGET_EFAULT;
|
||||
|
||||
ret = -TARGET_ENOSYS;
|
||||
#ifdef __NR_semtimedop
|
||||
ret = get_errno(safe_semtimedop(semid, sops, nsops, NULL));
|
||||
ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
|
||||
#endif
|
||||
#ifdef __NR_ipc
|
||||
if (ret == -TARGET_ENOSYS) {
|
||||
ret = get_errno(safe_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, 0));
|
||||
ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
|
||||
SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct target_msqid_ds
|
||||
{
|
||||
@ -4056,8 +4090,13 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
||||
#endif
|
||||
#ifdef __NR_ipc
|
||||
if (ret == -TARGET_ENOSYS) {
|
||||
#ifdef __s390x__
|
||||
ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
|
||||
host_mb));
|
||||
#else
|
||||
ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
|
||||
host_mb, 0));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
g_free(host_mb);
|
||||
@ -4066,6 +4105,20 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __NR_ipc
|
||||
#if defined(__sparc__)
|
||||
/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
|
||||
#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
|
||||
#elif defined(__s390x__)
|
||||
/* The s390 sys_ipc variant has only five parameters. */
|
||||
#define MSGRCV_ARGS(__msgp, __msgtyp) \
|
||||
((long int[]){(long int)__msgp, __msgtyp})
|
||||
#else
|
||||
#define MSGRCV_ARGS(__msgp, __msgtyp) \
|
||||
((long int[]){(long int)__msgp, __msgtyp}), 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
||||
ssize_t msgsz, abi_long msgtyp,
|
||||
int msgflg)
|
||||
@ -4094,7 +4147,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
||||
#ifdef __NR_ipc
|
||||
if (ret == -TARGET_ENOSYS) {
|
||||
ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
|
||||
msgflg, host_mb, msgtyp));
|
||||
msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4372,7 +4425,20 @@ static abi_long do_ipc(CPUArchState *cpu_env,
|
||||
|
||||
switch (call) {
|
||||
case IPCOP_semop:
|
||||
ret = do_semop(first, ptr, second);
|
||||
ret = do_semtimedop(first, ptr, second, 0);
|
||||
break;
|
||||
case IPCOP_semtimedop:
|
||||
/*
|
||||
* The s390 sys_ipc variant has only five parameters instead of six
|
||||
* (as for default variant) and the only difference is the handling of
|
||||
* SEMTIMEDOP where on s390 the third parameter is used as a pointer
|
||||
* to a struct timespec where the generic variant uses fifth parameter.
|
||||
*/
|
||||
#if defined(TARGET_S390X)
|
||||
ret = do_semtimedop(first, ptr, second, third);
|
||||
#else
|
||||
ret = do_semtimedop(first, ptr, second, fifth);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case IPCOP_semget:
|
||||
@ -9684,7 +9750,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
#endif
|
||||
#ifdef TARGET_NR_semop
|
||||
case TARGET_NR_semop:
|
||||
return do_semop(arg1, arg2, arg3);
|
||||
return do_semtimedop(arg1, arg2, arg3, 0);
|
||||
#endif
|
||||
#ifdef TARGET_NR_semtimedop
|
||||
case TARGET_NR_semtimedop:
|
||||
return do_semtimedop(arg1, arg2, arg3, arg4);
|
||||
#endif
|
||||
#ifdef TARGET_NR_semctl
|
||||
case TARGET_NR_semctl:
|
||||
|
Loading…
Reference in New Issue
Block a user