From 4e9fa8cb695c043652b4c5168edad95366b0e72a Mon Sep 17 00:00:00 2001 From: Lubos Dolezel Date: Sat, 22 Jul 2017 16:00:55 +0200 Subject: [PATCH] Use XNU's ported code for psynch implementation (fixes #251) --- src/kernel/emulation/linux/CMakeLists.txt | 5 ++++ .../emulation/linux/psynch/psynch_cvbroad.c | 19 +++++++-------- .../emulation/linux/psynch/psynch_cvbroad.h | 4 ++-- .../linux/psynch/psynch_cvclrprepost.c | 24 +++++++++++++++++++ .../linux/psynch/psynch_cvclrprepost.h | 8 +++++++ .../emulation/linux/psynch/psynch_cvsignal.c | 15 ++++++------ .../emulation/linux/psynch/psynch_cvsignal.h | 4 ++-- .../emulation/linux/psynch/psynch_cvwait.c | 13 +++++----- .../emulation/linux/psynch/psynch_errno.c | 18 ++++++++++++++ .../emulation/linux/psynch/psynch_errno.h | 7 ++++++ .../emulation/linux/psynch/psynch_mutexdrop.c | 5 ++-- .../emulation/linux/psynch/psynch_mutexwait.c | 5 ++-- .../emulation/linux/psynch/psynch_rw_rdlock.c | 22 +++++++++++++++++ .../emulation/linux/psynch/psynch_rw_rdlock.h | 8 +++++++ .../emulation/linux/psynch/psynch_rw_unlock.c | 22 +++++++++++++++++ .../emulation/linux/psynch/psynch_rw_unlock.h | 8 +++++++ .../emulation/linux/psynch/psynch_rw_wrlock.c | 22 +++++++++++++++++ .../emulation/linux/psynch/psynch_rw_wrlock.h | 8 +++++++ src/kernel/emulation/linux/syscalls.c | 8 +++++++ src/lkm | 2 +- 20 files changed, 194 insertions(+), 33 deletions(-) create mode 100644 src/kernel/emulation/linux/psynch/psynch_cvclrprepost.c create mode 100644 src/kernel/emulation/linux/psynch/psynch_cvclrprepost.h create mode 100644 src/kernel/emulation/linux/psynch/psynch_errno.c create mode 100644 src/kernel/emulation/linux/psynch/psynch_errno.h create mode 100644 src/kernel/emulation/linux/psynch/psynch_rw_rdlock.c create mode 100644 src/kernel/emulation/linux/psynch/psynch_rw_rdlock.h create mode 100644 src/kernel/emulation/linux/psynch/psynch_rw_unlock.c create mode 100644 src/kernel/emulation/linux/psynch/psynch_rw_unlock.h create mode 100644 src/kernel/emulation/linux/psynch/psynch_rw_wrlock.c create mode 100644 src/kernel/emulation/linux/psynch/psynch_rw_wrlock.h diff --git a/src/kernel/emulation/linux/CMakeLists.txt b/src/kernel/emulation/linux/CMakeLists.txt index a354277e8..e025a338d 100644 --- a/src/kernel/emulation/linux/CMakeLists.txt +++ b/src/kernel/emulation/linux/CMakeLists.txt @@ -241,6 +241,11 @@ set(emulation_sources bsdthread/__pthread_canceled.c bsdthread/pthread_chdir.c bsdthread/pthread_fchdir.c + psynch/psynch_errno.c + psynch/psynch_rw_rdlock.c + psynch/psynch_rw_wrlock.c + psynch/psynch_rw_unlock.c + psynch/psynch_cvclrprepost.c psynch/psynch_mutexwait.c psynch/psynch_mutexdrop.c psynch/psynch_cvwait.c diff --git a/src/kernel/emulation/linux/psynch/psynch_cvbroad.c b/src/kernel/emulation/linux/psynch/psynch_cvbroad.c index ba6bf30dc..0ebca4299 100644 --- a/src/kernel/emulation/linux/psynch/psynch_cvbroad.c +++ b/src/kernel/emulation/linux/psynch/psynch_cvbroad.c @@ -1,27 +1,24 @@ #include "psynch_cvbroad.h" #include "../base.h" -#include "../errno.h" +#include "psynch_errno.h" #include #include "../mach/lkm.h" #include "../../../../lkm/api.h" -#include "../simple.h" -long sys_psynch_cvbroad(void* cv, uint32_t cvgen, uint32_t diffgen, void* mutex, uint32_t mgen, - uint32_t ugen, uint64_t tid, uint32_t flags) +long sys_psynch_cvbroad(void* cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, void* mutex, uint64_t mugen, + uint64_t tid) { struct psynch_cvbroad_args args = { .cv = cv, - .cvgen = cvgen, - .diffgen = diffgen, + .cvlsgen = cvlsgen, + .cvudgen = cvudgen, .mutex = mutex, - .mgen = mgen, - .ugen = ugen, + .mugen = mugen, .tid = tid, .flags = flags, }; - // __simple_printf("sys_psynch_mutexwait(mutex=%p, mgen=%x)\n", mutex, mgen); - - return lkm_call(NR_psynch_cvbroad_trap, &args); + int rv = lkm_call(NR_psynch_cvbroad_trap, &args); + return psynch_errno(rv); } diff --git a/src/kernel/emulation/linux/psynch/psynch_cvbroad.h b/src/kernel/emulation/linux/psynch/psynch_cvbroad.h index 5fa75603f..d39bfc29d 100644 --- a/src/kernel/emulation/linux/psynch/psynch_cvbroad.h +++ b/src/kernel/emulation/linux/psynch/psynch_cvbroad.h @@ -2,8 +2,8 @@ #define LINUX_PSYNCH_CVBROAD_H #include -long sys_psynch_cvbroad(void* cv, uint32_t cvgen, uint32_t diffgen, void* mutex, uint32_t mgen, - uint32_t ugen, uint64_t tid, uint32_t flags); +long sys_psynch_cvbroad(void* cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, void* mutex, uint64_t mugen, + uint64_t tid); #endif diff --git a/src/kernel/emulation/linux/psynch/psynch_cvclrprepost.c b/src/kernel/emulation/linux/psynch/psynch_cvclrprepost.c new file mode 100644 index 000000000..0d9641dd0 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_cvclrprepost.c @@ -0,0 +1,24 @@ +#include "psynch_cvclrprepost.h" +#include "../base.h" +#include "psynch_errno.h" +#include +#include "../mach/lkm.h" +#include "../../../../lkm/api.h" +#include "../simple.h" + +long sys_psynch_cvclrprepost(void* cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags) +{ + struct psynch_cvclrprepost_args args = { + .cv = cv, + .cvgen = cvgen, + .cvugen = cvugen, + .cvsgen = cvsgen, + .prepocnt = prepocnt, + .preposeq = preposeq, + .flags = flags + }; + + int rv = lkm_call(NR_psynch_cvclrprepost, &args); + return psynch_errno(rv); +} + diff --git a/src/kernel/emulation/linux/psynch/psynch_cvclrprepost.h b/src/kernel/emulation/linux/psynch/psynch_cvclrprepost.h new file mode 100644 index 000000000..f7d7374bb --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_cvclrprepost.h @@ -0,0 +1,8 @@ +#ifndef LINUX_PSYNCH_CVCLRPREPOST_H +#define LINUX_PSYNCH_CVCLRPREPOST_H +#include + +long sys_psynch_cvclrprepost(void* cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags); + +#endif + diff --git a/src/kernel/emulation/linux/psynch/psynch_cvsignal.c b/src/kernel/emulation/linux/psynch/psynch_cvsignal.c index bc5e4991e..a3c954a84 100644 --- a/src/kernel/emulation/linux/psynch/psynch_cvsignal.c +++ b/src/kernel/emulation/linux/psynch/psynch_cvsignal.c @@ -1,27 +1,28 @@ #include "psynch_cvsignal.h" #include "../base.h" -#include "../errno.h" +#include "psynch_errno.h" #include #include "../mach/lkm.h" #include "../../../../lkm/api.h" #include "../simple.h" -long sys_psynch_cvsignal(void* cv, uint32_t cvgen, uint32_t cvugen, void* mutex, uint32_t mgen, - uint32_t ugen, int thread_port, uint32_t flags) +long sys_psynch_cvsignal(void* cv, uint32_t cvlsgen, uint32_t cvugen, int thread_port, void* mutex, uint32_t mugen, + uint64_t tid, uint32_t flags) { struct psynch_cvsignal_args args = { .cv = cv, - .cvgen = cvgen, + .cvlsgen = cvlsgen, .cvugen = cvugen, .mutex = mutex, - .mgen = mgen, - .ugen = ugen, + .mugen = mugen, + .tid = tid, .thread_port = thread_port, .flags = flags, }; // __simple_printf("sys_psynch_mutexwait(mutex=%p, mgen=%x)\n", mutex, mgen); - return lkm_call(NR_psynch_cvsignal_trap, &args); + int rv = lkm_call(NR_psynch_cvsignal_trap, &args); + return psynch_errno(rv); } diff --git a/src/kernel/emulation/linux/psynch/psynch_cvsignal.h b/src/kernel/emulation/linux/psynch/psynch_cvsignal.h index ae2da45c7..1e47d2f7c 100644 --- a/src/kernel/emulation/linux/psynch/psynch_cvsignal.h +++ b/src/kernel/emulation/linux/psynch/psynch_cvsignal.h @@ -2,8 +2,8 @@ #define LINUX_PSYNCH_CVSIGNAL_H #include -long sys_psynch_cvsignal(void* cv, uint32_t cvgen, uint32_t cvugen, void* mutex, uint32_t mgen, - uint32_t ugen, int thread_port, uint32_t flags); +long sys_psynch_cvsignal(void* cv, uint32_t cvlsgen, uint32_t cvugen, int thread_port, void* mutex, uint32_t mugen, + uint64_t tid, uint32_t flags); #endif diff --git a/src/kernel/emulation/linux/psynch/psynch_cvwait.c b/src/kernel/emulation/linux/psynch/psynch_cvwait.c index c8e3ccdc0..82b181290 100644 --- a/src/kernel/emulation/linux/psynch/psynch_cvwait.c +++ b/src/kernel/emulation/linux/psynch/psynch_cvwait.c @@ -1,6 +1,6 @@ #include "psynch_cvwait.h" #include "../base.h" -#include "../errno.h" +#include "psynch_errno.h" #include #include "../mach/lkm.h" #include "../../../../lkm/api.h" @@ -11,17 +11,18 @@ long sys_psynch_cvwait(void* cv, uint32_t cvgen, uint32_t cvugen, void* mutex, u { struct psynch_cvwait_args args = { .cv = cv, - .cvgen = cvgen, + .cvlsgen = cvgen, .cvugen = cvugen, .mutex = mutex, - .mgen = mgen, - .ugen = ugen, + .mugen = mgen, + .flags = ugen, .sec = sec, - .usec = usec, + .nsec = usec, }; // __simple_printf("sys_psynch_mutexwait(mutex=%p, mgen=%x)\n", mutex, mgen); - return lkm_call(NR_psynch_cvwait_trap, &args); + int rv = lkm_call(NR_psynch_cvwait_trap, &args); + return psynch_errno(rv); } diff --git a/src/kernel/emulation/linux/psynch/psynch_errno.c b/src/kernel/emulation/linux/psynch/psynch_errno.c new file mode 100644 index 000000000..7a25e84fa --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_errno.c @@ -0,0 +1,18 @@ +#include "../errno.h" + +// psynch syscalls send back extra bits and leave only the bottom 8 bits for errors +// So we have to filter out the top 24 bits, translate errno and put the 24 bits back. +int psynch_errno(int rv) +{ + int top; + if (rv >= 0) + return rv; + + rv = -rv; + top = rv & 0xffffff00; + rv = errno_linux_to_bsd(rv & 0xff); + rv |= top; + + return -rv; +} + diff --git a/src/kernel/emulation/linux/psynch/psynch_errno.h b/src/kernel/emulation/linux/psynch/psynch_errno.h new file mode 100644 index 000000000..967d986c1 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_errno.h @@ -0,0 +1,7 @@ +#ifndef _PSYNCH_ERRNO_H +#define _PSYNCH_ERRNO_H + +int psynch_errno(int rv); + +#endif + diff --git a/src/kernel/emulation/linux/psynch/psynch_mutexdrop.c b/src/kernel/emulation/linux/psynch/psynch_mutexdrop.c index b940fc5f6..496dcdd21 100644 --- a/src/kernel/emulation/linux/psynch/psynch_mutexdrop.c +++ b/src/kernel/emulation/linux/psynch/psynch_mutexdrop.c @@ -1,6 +1,6 @@ #include "psynch_mutexdrop.h" #include "../base.h" -#include "../errno.h" +#include "psynch_errno.h" #include #include "../mach/lkm.h" #include "../../../../lkm/api.h" @@ -18,6 +18,7 @@ long sys_psynch_mutexdrop(void* mutex, uint32_t mgen, uint32_t ugen, uint64_t ti // __simple_printf("sys_psynch_mutexdrop(mutex=%p, mgen=%x)\n", mutex, mgen); - return lkm_call(NR_psynch_mutexdrop_trap, &args); + int rv = lkm_call(NR_psynch_mutexdrop_trap, &args); + return psynch_errno(rv); } diff --git a/src/kernel/emulation/linux/psynch/psynch_mutexwait.c b/src/kernel/emulation/linux/psynch/psynch_mutexwait.c index 82a560355..d582d60f2 100644 --- a/src/kernel/emulation/linux/psynch/psynch_mutexwait.c +++ b/src/kernel/emulation/linux/psynch/psynch_mutexwait.c @@ -1,6 +1,6 @@ #include "psynch_mutexwait.h" #include "../base.h" -#include "../errno.h" +#include "psynch_errno.h" #include #include "../mach/lkm.h" #include "../../../../lkm/api.h" @@ -18,6 +18,7 @@ long sys_psynch_mutexwait(void* mutex, uint32_t mgen, uint32_t ugen, uint64_t ti // __simple_printf("sys_psynch_mutexwait(mutex=%p, mgen=%x)\n", mutex, mgen); - return lkm_call(NR_psynch_mutexwait_trap, &args); + int rv = lkm_call(NR_psynch_mutexwait_trap, &args); + return psynch_errno(rv); } diff --git a/src/kernel/emulation/linux/psynch/psynch_rw_rdlock.c b/src/kernel/emulation/linux/psynch/psynch_rw_rdlock.c new file mode 100644 index 000000000..f0b188d08 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_rw_rdlock.c @@ -0,0 +1,22 @@ +#include "psynch_rw_rdlock.h" +#include "../base.h" +#include "psynch_errno.h" +#include +#include "../mach/lkm.h" +#include "../../../../lkm/api.h" +#include "../simple.h" + +long sys_psynch_rw_rdlock(void* rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags) +{ + struct psynch_rw_rdlock_args args = { + .rwlock = rwlock, + .lgenval = lgenval, + .ugenval = ugenval, + .rw_wc = rw_wc, + .flags = flags + }; + + int rv = lkm_call(NR_psynch_rw_rdlock, &args); + return psynch_errno(rv); +} + diff --git a/src/kernel/emulation/linux/psynch/psynch_rw_rdlock.h b/src/kernel/emulation/linux/psynch/psynch_rw_rdlock.h new file mode 100644 index 000000000..d72265f43 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_rw_rdlock.h @@ -0,0 +1,8 @@ +#ifndef LINUX_PSYNCH_RW_RDLOCK_H +#define LINUX_PSYNCH_RW_RDLOCK_H +#include + +long sys_psynch_rw_rdlock(void* rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); + +#endif + diff --git a/src/kernel/emulation/linux/psynch/psynch_rw_unlock.c b/src/kernel/emulation/linux/psynch/psynch_rw_unlock.c new file mode 100644 index 000000000..728eb1268 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_rw_unlock.c @@ -0,0 +1,22 @@ +#include "psynch_rw_unlock.h" +#include "../base.h" +#include "psynch_errno.h" +#include +#include "../mach/lkm.h" +#include "../../../../lkm/api.h" +#include "../simple.h" + +long sys_psynch_rw_unlock(void* rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags) +{ + struct psynch_rw_unlock_args args = { + .rwlock = rwlock, + .lgenval = lgenval, + .ugenval = ugenval, + .rw_wc = rw_wc, + .flags = flags + }; + + int rv = lkm_call(NR_psynch_rw_unlock, &args); + return psynch_errno(rv); +} + diff --git a/src/kernel/emulation/linux/psynch/psynch_rw_unlock.h b/src/kernel/emulation/linux/psynch/psynch_rw_unlock.h new file mode 100644 index 000000000..540c6a059 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_rw_unlock.h @@ -0,0 +1,8 @@ +#ifndef LINUX_PSYNCH_RW_UNLOCK_H +#define LINUX_PSYNCH_RW_UNLOCK_H +#include + +long sys_psynch_rw_unlock(void* rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); + +#endif + diff --git a/src/kernel/emulation/linux/psynch/psynch_rw_wrlock.c b/src/kernel/emulation/linux/psynch/psynch_rw_wrlock.c new file mode 100644 index 000000000..8062c09d3 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_rw_wrlock.c @@ -0,0 +1,22 @@ +#include "psynch_rw_wrlock.h" +#include "../base.h" +#include "psynch_errno.h" +#include +#include "../mach/lkm.h" +#include "../../../../lkm/api.h" +#include "../simple.h" + +long sys_psynch_rw_wrlock(void* rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags) +{ + struct psynch_rw_wrlock_args args = { + .rwlock = rwlock, + .lgenval = lgenval, + .ugenval = ugenval, + .rw_wc = rw_wc, + .flags = flags + }; + + int rv = lkm_call(NR_psynch_rw_wrlock, &args); + return psynch_errno(rv); +} + diff --git a/src/kernel/emulation/linux/psynch/psynch_rw_wrlock.h b/src/kernel/emulation/linux/psynch/psynch_rw_wrlock.h new file mode 100644 index 000000000..ae53f8ec3 --- /dev/null +++ b/src/kernel/emulation/linux/psynch/psynch_rw_wrlock.h @@ -0,0 +1,8 @@ +#ifndef LINUX_PSYNCH_RW_WRLOCK_H +#define LINUX_PSYNCH_RW_WRLOCK_H +#include + +long sys_psynch_rw_wrlock(void* rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); + +#endif + diff --git a/src/kernel/emulation/linux/syscalls.c b/src/kernel/emulation/linux/syscalls.c index c782f9aab..439343e26 100644 --- a/src/kernel/emulation/linux/syscalls.c +++ b/src/kernel/emulation/linux/syscalls.c @@ -176,6 +176,10 @@ #include "select/select.h" #include "select/pselect.h" #include "select/poll.h" +#include "psynch/psynch_rw_rdlock.h" +#include "psynch/psynch_rw_wrlock.h" +#include "psynch/psynch_rw_unlock.h" +#include "psynch/psynch_cvclrprepost.h" #include "psynch/psynch_mutexwait.h" #include "psynch/psynch_mutexdrop.h" #include "psynch/psynch_cvwait.h" @@ -348,7 +352,11 @@ void* __bsd_syscall_table[600] = { [303] = sys_psynch_cvbroad, [304] = sys_psynch_cvsignal, [305] = sys_psynch_cvwait, + [306] = sys_psynch_rw_rdlock, + [307] = sys_psynch_rw_wrlock, + [308] = sys_psynch_rw_unlock, [310] = sys_getsid, + [312] = sys_psynch_cvclrprepost, [322] = sys_iopolicysys, [327] = sys_issetugid, [328] = sys_pthread_kill, diff --git a/src/lkm b/src/lkm index 62bccfc1b..9bf64e025 160000 --- a/src/lkm +++ b/src/lkm @@ -1 +1 @@ -Subproject commit 62bccfc1b1fc2ec46a1e155edd9a2b184d681e13 +Subproject commit 9bf64e025441bce24aaff14b23574531d3f4f363 -- 2.51.2