Hello, I'm in the process of upgrading about a hundred 8.2-RELEASE systems to 11.0-RELEASE (maybe 11.1 by the time I'm finished), and hit a snag with one of my regression tests. It involves running 'jar' from jdk1.5.0 (originally built on 6.3-RELEASE I believe), which goes into a loop and hangs. Replicating it is very simple - just run 'jar' and instead of displaying the usage message, it starts spinning. I ran it under truss, and after some normal-looking things (like a bunch of compat6 syscalls) saw a bunch of this at the end: _umtx_op(0x641c10,UMTX_OP_RESERVED0,0x18947,0x0,0x0) ERR#45 'Operation not supported' Looking through the svn history, it appears that two umtx syscalls were removed in https://svnweb.freebsd.org/base?view=revision&revision=263318 and https://svnweb.freebsd.org/base?view=revision&revision=304525. I don't consider myself a kernel developer, but I managed to cobble together a patch that got them working again for my use case. There is currently a TODO regarding the error handling - I just wanted to prove this would work and fix the jar issue. Looking through the rest of the code, it feels to me like the correct thing to do is put this stuff back in under #ifdef COMPAT_FREEBSD6. I have attached a patch that resolves my issue with jar. If the above approach sounds reasonable, I can work on cleaning it up into an actual, acceptable, form. Thanks, -Nicholas diff -u -r src.fbsd11.stock/lib/libc/sys/Symbol.map src.oldumtx/lib/libc/sys/Symbol.map --- src.fbsd11.stock/lib/libc/sys/Symbol.map 2016-09-28 19:25:57.000000000 -0400 +++ src.oldumtx/lib/libc/sys/Symbol.map 2017-04-05 13:54:37.026112000 -0400 @@ -34,7 +34,9 @@ __setugid; __syscall; __sysctl; + _umtx_lock; _umtx_op; + _umtx_unlock; abort2; accept; access; @@ -453,8 +455,12 @@ __sys___syscall; ___sysctl; __sys___sysctl; + __umtx_lock; + __sys__umtx_lock; __umtx_op; __sys__umtx_op; + __umtx_unlock; + __sys__umtx_unlock; _abort2; __sys_abort2; _accept; diff -u -r src.fbsd11.stock/sys/compat/freebsd32/freebsd32_proto.h src.oldumtx/sys/compat/freebsd32/freebsd32_proto.h --- src.fbsd11.stock/sys/compat/freebsd32/freebsd32_proto.h 2016-09-28 19:24:55.000000000 -0400 +++ src.oldumtx/sys/compat/freebsd32/freebsd32_proto.h 2017-04-05 15:48:00.638984000 -0400 @@ -2,8 +2,8 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/compat/freebsd32/freebsd32_proto.h 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks */ #ifndef _FREEBSD32_SYSPROTO_H_ @@ -359,6 +359,12 @@ char oucp_l_[PADL_(struct freebsd32_ucontext *)]; struct freebsd32_ucontext * oucp; char oucp_r_[PADR_(struct freebsd32_ucontext *)]; char ucp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(const struct freebsd32_ucontext *)]; }; +struct freebsd32_umtx_lock_args { + char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)]; +}; +struct freebsd32_umtx_unlock_args { + char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)]; +}; struct freebsd32_ksem_timedwait_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; char abstime_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * abstime; char abstime_r_[PADR_(const struct timespec32 *)]; @@ -757,6 +763,8 @@ int freebsd32_getcontext(struct thread *, struct freebsd32_getcontext_args *); int freebsd32_setcontext(struct thread *, struct freebsd32_setcontext_args *); int freebsd32_swapcontext(struct thread *, struct freebsd32_swapcontext_args *); +int freebsd32_umtx_lock(struct thread *, struct freebsd32_umtx_lock_args *); +int freebsd32_umtx_unlock(struct thread *, struct freebsd32_umtx_unlock_args *); int freebsd32_ksem_timedwait(struct thread *, struct freebsd32_ksem_timedwait_args *); int freebsd32_thr_suspend(struct thread *, struct freebsd32_thr_suspend_args *); int freebsd32_umtx_op(struct thread *, struct freebsd32_umtx_op_args *); @@ -1223,6 +1231,8 @@ #define FREEBSD32_SYS_AUE_freebsd32_getcontext AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_setcontext AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_swapcontext AUE_NULL +#define FREEBSD32_SYS_AUE_freebsd32_umtx_lock AUE_NULL +#define FREEBSD32_SYS_AUE_freebsd32_umtx_unlock AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_ksem_timedwait AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_thr_suspend AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_umtx_op AUE_NULL diff -u -r src.fbsd11.stock/sys/compat/freebsd32/freebsd32_syscall.h src.oldumtx/sys/compat/freebsd32/freebsd32_syscall.h --- src.fbsd11.stock/sys/compat/freebsd32/freebsd32_syscall.h 2016-09-28 19:24:55.000000000 -0400 +++ src.oldumtx/sys/compat/freebsd32/freebsd32_syscall.h 2017-04-05 15:48:00.635260000 -0400 @@ -2,8 +2,8 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/compat/freebsd32/freebsd32_syscall.h 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks */ #define FREEBSD32_SYS_syscall 0 @@ -339,6 +339,8 @@ #define FREEBSD32_SYS_thr_exit 431 #define FREEBSD32_SYS_thr_self 432 #define FREEBSD32_SYS_thr_kill 433 +#define FREEBSD32_SYS_freebsd32_umtx_lock 434 +#define FREEBSD32_SYS_freebsd32_umtx_unlock 435 #define FREEBSD32_SYS_jail_attach 436 #define FREEBSD32_SYS_extattr_list_fd 437 #define FREEBSD32_SYS_extattr_list_file 438 diff -u -r src.fbsd11.stock/sys/compat/freebsd32/freebsd32_syscalls.c src.oldumtx/sys/compat/freebsd32/freebsd32_syscalls.c --- src.fbsd11.stock/sys/compat/freebsd32/freebsd32_syscalls.c 2016-09-28 19:24:55.000000000 -0400 +++ src.oldumtx/sys/compat/freebsd32/freebsd32_syscalls.c 2017-04-05 15:48:00.635249000 -0400 @@ -2,8 +2,8 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/compat/freebsd32/freebsd32_syscalls.c 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks */ const char *freebsd32_syscallnames[] = { @@ -444,8 +444,8 @@ "thr_exit", /* 431 = thr_exit */ "thr_self", /* 432 = thr_self */ "thr_kill", /* 433 = thr_kill */ - "#434", /* 434 = nosys */ - "#435", /* 435 = nosys */ + "freebsd32_umtx_lock", /* 434 = freebsd32_umtx_lock */ + "freebsd32_umtx_unlock", /* 435 = freebsd32_umtx_unlock */ "jail_attach", /* 436 = jail_attach */ "extattr_list_fd", /* 437 = extattr_list_fd */ "extattr_list_file", /* 438 = extattr_list_file */ diff -u -r src.fbsd11.stock/sys/compat/freebsd32/freebsd32_sysent.c src.oldumtx/sys/compat/freebsd32/freebsd32_sysent.c --- src.fbsd11.stock/sys/compat/freebsd32/freebsd32_sysent.c 2016-09-28 19:24:55.000000000 -0400 +++ src.oldumtx/sys/compat/freebsd32/freebsd32_sysent.c 2017-04-05 15:48:00.637117000 -0400 @@ -2,8 +2,8 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/compat/freebsd32/freebsd32_sysent.c 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/compat/freebsd32/syscalls.master 302094 2016-06-22 21:15:59Z brooks */ #include "opt_compat.h" @@ -487,8 +487,8 @@ { AS(thr_exit_args), (sy_call_t *)sys_thr_exit, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 431 = thr_exit */ { AS(thr_self_args), (sy_call_t *)sys_thr_self, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 432 = thr_self */ { AS(thr_kill_args), (sy_call_t *)sys_thr_kill, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 433 = thr_kill */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 434 = nosys */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 435 = nosys */ + { AS(freebsd32_umtx_lock_args), (sy_call_t *)freebsd32_umtx_lock, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 434 = freebsd32_umtx_lock */ + { AS(freebsd32_umtx_unlock_args), (sy_call_t *)freebsd32_umtx_unlock, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 435 = freebsd32_umtx_unlock */ { AS(jail_attach_args), (sy_call_t *)sys_jail_attach, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 436 = jail_attach */ { AS(extattr_list_fd_args), (sy_call_t *)sys_extattr_list_fd, AUE_EXTATTR_LIST_FD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 437 = extattr_list_fd */ { AS(extattr_list_file_args), (sy_call_t *)sys_extattr_list_file, AUE_EXTATTR_LIST_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 438 = extattr_list_file */ diff -u -r src.fbsd11.stock/sys/compat/freebsd32/freebsd32_systrace_args.c src.oldumtx/sys/compat/freebsd32/freebsd32_systrace_args.c --- src.fbsd11.stock/sys/compat/freebsd32/freebsd32_systrace_args.c 2016-09-28 19:24:55.000000000 -0400 +++ src.oldumtx/sys/compat/freebsd32/freebsd32_systrace_args.c 2017-04-05 15:48:00.641174000 -0400 @@ -2,7 +2,7 @@ * System call argument to DTrace register array converstion. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/compat/freebsd32/freebsd32_systrace_args.c 302095 2016-06-22 21:18:19Z brooks $ + * $FreeBSD$ * This file is part of the DTrace syscall provider. */ @@ -2200,6 +2200,20 @@ *n_args = 2; break; } + /* freebsd32_umtx_lock */ + case 434: { + struct freebsd32_umtx_lock_args *p = params; + uarg[0] = (intptr_t) p->umtx; /* struct umtx * */ + *n_args = 1; + break; + } + /* freebsd32_umtx_unlock */ + case 435: { + struct freebsd32_umtx_unlock_args *p = params; + uarg[0] = (intptr_t) p->umtx; /* struct umtx * */ + *n_args = 1; + break; + } /* jail_attach */ case 436: { struct jail_attach_args *p = params; @@ -6866,6 +6880,26 @@ break; }; break; + /* freebsd32_umtx_lock */ + case 434: + switch(ndx) { + case 0: + p = "struct umtx *"; + break; + default: + break; + }; + break; + /* freebsd32_umtx_unlock */ + case 435: + switch(ndx) { + case 0: + p = "struct umtx *"; + break; + default: + break; + }; + break; /* jail_attach */ case 436: switch(ndx) { @@ -10189,6 +10223,16 @@ if (ndx == 0 || ndx == 1) p = "int"; break; + /* freebsd32_umtx_lock */ + case 434: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* freebsd32_umtx_unlock */ + case 435: + if (ndx == 0 || ndx == 1) + p = "int"; + break; /* jail_attach */ case 436: if (ndx == 0 || ndx == 1) diff -u -r src.fbsd11.stock/sys/compat/freebsd32/syscalls.master src.oldumtx/sys/compat/freebsd32/syscalls.master --- src.fbsd11.stock/sys/compat/freebsd32/syscalls.master 2016-09-28 19:24:55.000000000 -0400 +++ src.oldumtx/sys/compat/freebsd32/syscalls.master 2017-04-04 14:06:39.408900000 -0400 @@ -777,8 +777,8 @@ 431 AUE_NULL NOPROTO { void thr_exit(long *state); } 432 AUE_NULL NOPROTO { int thr_self(long *id); } 433 AUE_NULL NOPROTO { int thr_kill(long id, int sig); } -434 AUE_NULL UNIMPL nosys -435 AUE_NULL UNIMPL nosys +434 AUE_NULL STD { int freebsd32_umtx_lock(struct umtx *umtx); } +435 AUE_NULL STD { int freebsd32_umtx_unlock(struct umtx *umtx); } 436 AUE_NULL NOPROTO { int jail_attach(int jid); } 437 AUE_EXTATTR_LIST_FD NOPROTO { ssize_t extattr_list_fd(int fd, \ int attrnamespace, void *data, \ diff -u -r src.fbsd11.stock/sys/kern/capabilities.conf src.oldumtx/sys/kern/capabilities.conf --- src.fbsd11.stock/sys/kern/capabilities.conf 2016-09-28 19:24:40.000000000 -0400 +++ src.oldumtx/sys/kern/capabilities.conf 2017-04-05 14:17:10.920476000 -0400 @@ -64,7 +64,9 @@ ## ## XXRW: Need to check this very carefully. ## +_umtx_lock _umtx_op +_umtx_unlock ## ## Allow process termination using abort2(2). diff -u -r src.fbsd11.stock/sys/kern/init_sysent.c src.oldumtx/sys/kern/init_sysent.c --- src.fbsd11.stock/sys/kern/init_sysent.c 2016-09-28 19:24:40.000000000 -0400 +++ src.oldumtx/sys/kern/init_sysent.c 2017-04-05 15:44:29.739973000 -0400 @@ -2,8 +2,8 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/kern/init_sysent.c 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery */ #include "opt_compat.h" @@ -480,8 +480,8 @@ { AS(thr_exit_args), (sy_call_t *)sys_thr_exit, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 431 = thr_exit */ { AS(thr_self_args), (sy_call_t *)sys_thr_self, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 432 = thr_self */ { AS(thr_kill_args), (sy_call_t *)sys_thr_kill, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 433 = thr_kill */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 434 = nosys */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 435 = nosys */ + { AS(_umtx_lock_args), (sy_call_t *)sys__umtx_lock, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 434 = _umtx_lock */ + { AS(_umtx_unlock_args), (sy_call_t *)sys__umtx_unlock, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 435 = _umtx_unlock */ { AS(jail_attach_args), (sy_call_t *)sys_jail_attach, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 436 = jail_attach */ { AS(extattr_list_fd_args), (sy_call_t *)sys_extattr_list_fd, AUE_EXTATTR_LIST_FD, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 437 = extattr_list_fd */ { AS(extattr_list_file_args), (sy_call_t *)sys_extattr_list_file, AUE_EXTATTR_LIST_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 438 = extattr_list_file */ diff -u -r src.fbsd11.stock/sys/kern/kern_umtx.c src.oldumtx/sys/kern/kern_umtx.c --- src.fbsd11.stock/sys/kern/kern_umtx.c 2016-09-28 19:24:40.000000000 -0400 +++ src.oldumtx/sys/kern/kern_umtx.c 2017-04-05 15:52:53.900304000 -0400 @@ -909,6 +909,367 @@ } /* + * Lock a umtx object. + */ +static int +do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id, + const struct timespec *timeout) +{ + struct abs_timeout timo; + struct umtx_q *uq; + u_long owner; + u_long old; + int error = 0; + + uq = td->td_umtxq; + if (timeout != NULL) + abs_timeout_init(&timo, CLOCK_REALTIME, 0, timeout); + + /* + * Care must be exercised when dealing with umtx structure. It + * can fault on any access. + */ + for (;;) { + /* + * Try the uncontested case. This should be done in userland. + */ + owner = casuword(&umtx->u_owner, UMTX_UNOWNED, id); + + /* The acquire succeeded. */ + if (owner == UMTX_UNOWNED) + return (0); + + /* The address was invalid. */ + if (owner == -1) + return (EFAULT); + + /* If no one owns it but it is contested try to acquire it. */ + if (owner == UMTX_CONTESTED) { + owner = casuword(&umtx->u_owner, + UMTX_CONTESTED, id | UMTX_CONTESTED); + + if (owner == UMTX_CONTESTED) + return (0); + + /* The address was invalid. */ + if (owner == -1) + return (EFAULT); + + error = umtxq_check_susp(td); + if (error != 0) + break; + + /* If this failed the lock has changed, restart. */ + continue; + } + + /* + * If we caught a signal, we have retried and now + * exit immediately. + */ + if (error != 0) + break; + + if ((error = umtx_key_get(umtx, TYPE_SIMPLE_LOCK, + AUTO_SHARE, &uq->uq_key)) != 0) + return (error); + + umtxq_lock(&uq->uq_key); + umtxq_busy(&uq->uq_key); + umtxq_insert(uq); + umtxq_unbusy(&uq->uq_key); + umtxq_unlock(&uq->uq_key); + + /* + * Set the contested bit so that a release in user space + * knows to use the system call for unlock. If this fails + * either some one else has acquired the lock or it has been + * released. + */ + old = casuword(&umtx->u_owner, owner, owner | UMTX_CONTESTED); + + /* The address was invalid. */ + if (old == -1) { + umtxq_lock(&uq->uq_key); + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + return (EFAULT); + } + + /* + * We set the contested bit, sleep. Otherwise the lock changed + * and we need to retry or we lost a race to the thread + * unlocking the umtx. + */ + umtxq_lock(&uq->uq_key); + if (old == owner) + error = umtxq_sleep(uq, "umtx", timeout == NULL ? NULL : + &timo); + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + + if (error == 0) + error = umtxq_check_susp(td); + } + + if (timeout == NULL) { + /* Mutex locking is restarted if it is interrupted. */ + if (error == EINTR) + error = ERESTART; + } else { + /* Timed-locking is not restarted. */ + if (error == ERESTART) + error = EINTR; + } + return (error); +} + +/* + * Unlock a umtx object. + */ +static int +do_unlock_umtx(struct thread *td, struct umtx *umtx, u_long id) +{ + struct umtx_key key; + u_long owner; + u_long old; + int error; + int count; + + /* + * Make sure we own this mtx. + */ + owner = fuword(__DEVOLATILE(u_long *, &umtx->u_owner)); + if (owner == -1) + return (EFAULT); + + if ((owner & ~UMTX_CONTESTED) != id) + return (EPERM); + + /* This should be done in userland */ + if ((owner & UMTX_CONTESTED) == 0) { + old = casuword(&umtx->u_owner, owner, UMTX_UNOWNED); + if (old == -1) + return (EFAULT); + if (old == owner) + return (0); + owner = old; + } + + /* We should only ever be in here for contested locks */ + if ((error = umtx_key_get(umtx, TYPE_SIMPLE_LOCK, AUTO_SHARE, + &key)) != 0) + return (error); + + umtxq_lock(&key); + umtxq_busy(&key); + count = umtxq_count(&key); + umtxq_unlock(&key); + + /* + * When unlocking the umtx, it must be marked as unowned if + * there is zero or one thread only waiting for it. + * Otherwise, it must be marked as contested. + */ + old = casuword(&umtx->u_owner, owner, + count <= 1 ? UMTX_UNOWNED : UMTX_CONTESTED); + umtxq_lock(&key); + umtxq_signal(&key,1); + umtxq_unbusy(&key); + umtxq_unlock(&key); + umtx_key_release(&key); + if (old == -1) + return (EFAULT); + if (old != owner) + return (EINVAL); + return (0); +} + +#ifdef COMPAT_FREEBSD32 + +/* + * Lock a umtx object. + */ +static int +do_lock_umtx32(struct thread *td, uint32_t *m, uint32_t id, + const struct timespec *timeout) +{ + struct abs_timeout timo; + struct umtx_q *uq; + uint32_t owner; + uint32_t old; + int error = 0; + + uq = td->td_umtxq; + + if (timeout != NULL) + abs_timeout_init(&timo, CLOCK_REALTIME, 0, timeout); + + /* + * Care must be exercised when dealing with umtx structure. It + * can fault on any access. + */ + for (;;) { + /* + * Try the uncontested case. This should be done in userland. + */ + owner = casuword32(m, UMUTEX_UNOWNED, id); + + /* The acquire succeeded. */ + if (owner == UMUTEX_UNOWNED) + return (0); + + /* The address was invalid. */ + if (owner == -1) + return (EFAULT); + + /* If no one owns it but it is contested try to acquire it. */ + if (owner == UMUTEX_CONTESTED) { + owner = casuword32(m, + UMUTEX_CONTESTED, id | UMUTEX_CONTESTED); + if (owner == UMUTEX_CONTESTED) + return (0); + + /* The address was invalid. */ + if (owner == -1) + return (EFAULT); + + error = umtxq_check_susp(td); + if (error != 0) + break; + + /* If this failed the lock has changed, restart. */ + continue; + } + + /* + * If we caught a signal, we have retried and now + * exit immediately. + */ + if (error != 0) + return (error); + + if ((error = umtx_key_get(m, TYPE_SIMPLE_LOCK, + AUTO_SHARE, &uq->uq_key)) != 0) + return (error); + + umtxq_lock(&uq->uq_key); + umtxq_busy(&uq->uq_key); + umtxq_insert(uq); + umtxq_unbusy(&uq->uq_key); + umtxq_unlock(&uq->uq_key); + + /* + * Set the contested bit so that a release in user space + * knows to use the system call for unlock. If this fails + * either some one else has acquired the lock or it has been + * released. + */ + old = casuword32(m, owner, owner | UMUTEX_CONTESTED); + + /* The address was invalid. */ + if (old == -1) { + umtxq_lock(&uq->uq_key); + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + return (EFAULT); + } + + /* + * We set the contested bit, sleep. Otherwise the lock changed + * and we need to retry or we lost a race to the thread + * unlocking the umtx. + */ + umtxq_lock(&uq->uq_key); + if (old == owner) + error = umtxq_sleep(uq, "umtx", timeout == NULL ? + NULL : &timo); + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + + if (error == 0) + error = umtxq_check_susp(td); + } + + if (timeout == NULL) { + /* Mutex locking is restarted if it is interrupted. */ + if (error == EINTR) + error = ERESTART; + } else { + /* Timed-locking is not restarted. */ + if (error == ERESTART) + error = EINTR; + } + return (error); +} + +/* + * Unlock a umtx object. + */ +static int +do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id) +{ + struct umtx_key key; + uint32_t owner; + uint32_t old; + int error; + int count; + + /* + * Make sure we own this mtx. + */ + owner = fuword32(m); + if (owner == -1) + return (EFAULT); + + if ((owner & ~UMUTEX_CONTESTED) != id) + return (EPERM); + + /* This should be done in userland */ + if ((owner & UMUTEX_CONTESTED) == 0) { + old = casuword32(m, owner, UMUTEX_UNOWNED); + if (old == -1) + return (EFAULT); + if (old == owner) + return (0); + owner = old; + } + + /* We should only ever be in here for contested locks */ + if ((error = umtx_key_get(m, TYPE_SIMPLE_LOCK, AUTO_SHARE, + &key)) != 0) + return (error); + + umtxq_lock(&key); + umtxq_busy(&key); + count = umtxq_count(&key); + umtxq_unlock(&key); + + /* + * When unlocking the umtx, it must be marked as unowned if + * there is zero or one thread only waiting for it. + * Otherwise, it must be marked as contested. + */ + old = casuword32(m, owner, + count <= 1 ? UMUTEX_UNOWNED : UMUTEX_CONTESTED); + umtxq_lock(&key); + umtxq_signal(&key,1); + umtxq_unbusy(&key); + umtxq_unlock(&key); + umtx_key_release(&key); + if (old == -1) + return (EFAULT); + if (old != owner) + return (EINVAL); + return (0); +} +#endif + +/* * Fetch and compare value, sleep on the address if value is not changed. */ static int @@ -1078,6 +1439,10 @@ } } + if ((flags & UMUTEX_ERROR_CHECK) != 0 && + (owner & ~UMUTEX_CONTESTED) == id) + return (EDEADLK); + if (mode == _UMUTEX_TRY) return (EBUSY); @@ -1880,6 +2245,12 @@ break; } + if ((flags & UMUTEX_ERROR_CHECK) != 0 && + (owner & ~UMUTEX_CONTESTED) == id) { + error = EDEADLK; + break; + } + if (try != 0) { error = EBUSY; break; @@ -2149,6 +2520,12 @@ break; } + if ((flags & UMUTEX_ERROR_CHECK) != 0 && + (owner & ~UMUTEX_CONTESTED) == id) { + error = EDEADLK; + break; + } + if (try != 0) { error = EBUSY; break; @@ -3258,6 +3635,20 @@ return (error); } +int +sys__umtx_lock(struct thread *td, struct _umtx_lock_args *uap) + /* struct umtx *umtx */ +{ + return do_lock_umtx(td, uap->umtx, td->td_tid, 0); +} + +int +sys__umtx_unlock(struct thread *td, struct _umtx_unlock_args *uap) + /* struct umtx *umtx */ +{ + return do_unlock_umtx(td, uap->umtx, td->td_tid); +} + inline int umtx_copyin_timeout(const void *addr, struct timespec *tsp) { @@ -3293,10 +3684,27 @@ } static int -__umtx_op_unimpl(struct thread *td, struct _umtx_op_args *uap) +__umtx_op_lock_umtx(struct thread *td, struct _umtx_op_args *uap) { + struct timespec *ts, timeout; + int error; + + /* Allow a null timespec (wait forever). */ + if (uap->uaddr2 == NULL) + ts = NULL; + else { + error = umtx_copyin_timeout(uap->uaddr2, &timeout); + if (error != 0) + return (error); + ts = &timeout; + } + return (do_lock_umtx(td, uap->obj, uap->val, ts)); +} - return (EOPNOTSUPP); +static int +__umtx_op_unlock_umtx(struct thread *td, struct _umtx_op_args *uap) +{ + return (do_unlock_umtx(td, uap->obj, uap->val)); } static int @@ -3926,8 +4334,8 @@ typedef int (*_umtx_op_func)(struct thread *td, struct _umtx_op_args *uap); static const _umtx_op_func op_table[] = { - [UMTX_OP_RESERVED0] = __umtx_op_unimpl, - [UMTX_OP_RESERVED1] = __umtx_op_unimpl, + [UMTX_OP_LOCK] = __umtx_op_lock_umtx, + [UMTX_OP_UNLOCK] = __umtx_op_unlock_umtx, [UMTX_OP_WAIT] = __umtx_op_wait, [UMTX_OP_WAKE] = __umtx_op_wake, [UMTX_OP_MUTEX_TRYLOCK] = __umtx_op_trylock_umutex, @@ -3970,6 +4378,19 @@ } #ifdef COMPAT_FREEBSD32 +int +freebsd32_umtx_lock(struct thread *td, struct freebsd32_umtx_lock_args *uap) + /* struct umtx *umtx */ +{ + return (do_lock_umtx32(td, (uint32_t *)uap->umtx, td->td_tid, NULL)); +} + +int +freebsd32_umtx_unlock(struct thread *td, struct freebsd32_umtx_unlock_args *uap) + /* struct umtx *umtx */ +{ + return (do_unlock_umtx32(td, (uint32_t *)uap->umtx, td->td_tid)); +} struct timespec32 { int32_t tv_sec; @@ -4027,6 +4448,30 @@ } static int +__umtx_op_lock_umtx_compat32(struct thread *td, struct _umtx_op_args *uap) +{ + struct timespec *ts, timeout; + int error; + + /* Allow a null timespec (wait forever). */ + if (uap->uaddr2 == NULL) + ts = NULL; + else { + error = umtx_copyin_timeout32(uap->uaddr2, &timeout); + if (error != 0) + return (error); + ts = &timeout; + } + return (do_lock_umtx32(td, uap->obj, uap->val, ts)); +} + +static int +__umtx_op_unlock_umtx_compat32(struct thread *td, struct _umtx_op_args *uap) +{ + return (do_unlock_umtx32(td, uap->obj, (uint32_t)uap->val)); +} + +static int __umtx_op_wait_compat32(struct thread *td, struct _umtx_op_args *uap) { struct _umtx_time *tm_p, timeout; @@ -4245,8 +4690,8 @@ } static const _umtx_op_func op_table_compat32[] = { - [UMTX_OP_RESERVED0] = __umtx_op_unimpl, - [UMTX_OP_RESERVED1] = __umtx_op_unimpl, + [UMTX_OP_LOCK] = __umtx_op_lock_umtx_compat32, + [UMTX_OP_UNLOCK] = __umtx_op_unlock_umtx_compat32, [UMTX_OP_WAIT] = __umtx_op_wait_compat32, [UMTX_OP_WAKE] = __umtx_op_wake, [UMTX_OP_MUTEX_TRYLOCK] = __umtx_op_trylock_umutex, diff -u -r src.fbsd11.stock/sys/kern/syscalls.c src.oldumtx/sys/kern/syscalls.c --- src.fbsd11.stock/sys/kern/syscalls.c 2016-09-28 19:24:40.000000000 -0400 +++ src.oldumtx/sys/kern/syscalls.c 2017-04-05 15:44:29.738110000 -0400 @@ -2,8 +2,8 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/kern/syscalls.c 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery */ const char *syscallnames[] = { @@ -441,8 +441,8 @@ "thr_exit", /* 431 = thr_exit */ "thr_self", /* 432 = thr_self */ "thr_kill", /* 433 = thr_kill */ - "#434", /* 434 = nosys */ - "#435", /* 435 = nosys */ + "_umtx_lock", /* 434 = _umtx_lock */ + "_umtx_unlock", /* 435 = _umtx_unlock */ "jail_attach", /* 436 = jail_attach */ "extattr_list_fd", /* 437 = extattr_list_fd */ "extattr_list_file", /* 438 = extattr_list_file */ diff -u -r src.fbsd11.stock/sys/kern/syscalls.master src.oldumtx/sys/kern/syscalls.master --- src.fbsd11.stock/sys/kern/syscalls.master 2016-09-28 19:24:40.000000000 -0400 +++ src.oldumtx/sys/kern/syscalls.master 2017-04-04 13:50:05.910545000 -0400 @@ -774,8 +774,8 @@ 431 AUE_NULL STD { void thr_exit(long *state); } 432 AUE_NULL STD { int thr_self(long *id); } 433 AUE_NULL STD { int thr_kill(long id, int sig); } -434 AUE_NULL UNIMPL nosys -435 AUE_NULL UNIMPL nosys +434 AUE_NULL STD { int _umtx_lock(struct umtx *umtx); } +435 AUE_NULL STD { int _umtx_unlock(struct umtx *umtx); } 436 AUE_NULL STD { int jail_attach(int jid); } 437 AUE_EXTATTR_LIST_FD STD { ssize_t extattr_list_fd(int fd, \ int attrnamespace, void *data, \ diff -u -r src.fbsd11.stock/sys/kern/systrace_args.c src.oldumtx/sys/kern/systrace_args.c --- src.fbsd11.stock/sys/kern/systrace_args.c 2016-09-28 19:24:40.000000000 -0400 +++ src.oldumtx/sys/kern/systrace_args.c 2017-04-05 15:44:29.743862000 -0400 @@ -2,7 +2,7 @@ * System call argument to DTrace register array converstion. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/kern/systrace_args.c 302095 2016-06-22 21:18:19Z brooks $ + * $FreeBSD$ * This file is part of the DTrace syscall provider. */ @@ -2362,6 +2362,20 @@ *n_args = 2; break; } + /* _umtx_lock */ + case 434: { + struct _umtx_lock_args *p = params; + uarg[0] = (intptr_t) p->umtx; /* struct umtx * */ + *n_args = 1; + break; + } + /* _umtx_unlock */ + case 435: { + struct _umtx_unlock_args *p = params; + uarg[0] = (intptr_t) p->umtx; /* struct umtx * */ + *n_args = 1; + break; + } /* jail_attach */ case 436: { struct jail_attach_args *p = params; @@ -7148,6 +7162,26 @@ break; }; break; + /* _umtx_lock */ + case 434: + switch(ndx) { + case 0: + p = "struct umtx *"; + break; + default: + break; + }; + break; + /* _umtx_unlock */ + case 435: + switch(ndx) { + case 0: + p = "struct umtx *"; + break; + default: + break; + }; + break; /* jail_attach */ case 436: switch(ndx) { @@ -10246,6 +10280,16 @@ if (ndx == 0 || ndx == 1) p = "int"; break; + /* _umtx_lock */ + case 434: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* _umtx_unlock */ + case 435: + if (ndx == 0 || ndx == 1) + p = "int"; + break; /* jail_attach */ case 436: if (ndx == 0 || ndx == 1) diff -u -r src.fbsd11.stock/sys/sys/_umtx.h src.oldumtx/sys/sys/_umtx.h --- src.fbsd11.stock/sys/sys/_umtx.h 2016-09-28 19:24:41.000000000 -0400 +++ src.oldumtx/sys/sys/_umtx.h 2017-04-04 13:51:15.942811000 -0400 @@ -33,6 +33,10 @@ #include <sys/_types.h> #include <sys/_timespec.h> +struct umtx { + volatile unsigned long u_owner; /*Owner of the mutex. */ +}; + struct umutex { volatile __lwpid_t m_owner; /* Owner of the mutex */ __uint32_t m_flags; /* Flags of the mutex */ diff -u -r src.fbsd11.stock/sys/sys/syscall.h src.oldumtx/sys/sys/syscall.h --- src.fbsd11.stock/sys/sys/syscall.h 2016-09-28 19:24:41.000000000 -0400 +++ src.oldumtx/sys/sys/syscall.h 2017-04-05 15:44:29.738119000 -0400 @@ -2,8 +2,8 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/sys/syscall.h 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery */ #define SYS_syscall 0 @@ -359,6 +359,8 @@ #define SYS_thr_exit 431 #define SYS_thr_self 432 #define SYS_thr_kill 433 +#define SYS__umtx_lock 434 +#define SYS__umtx_unlock 435 #define SYS_jail_attach 436 #define SYS_extattr_list_fd 437 #define SYS_extattr_list_file 438 diff -u -r src.fbsd11.stock/sys/sys/syscall.mk src.oldumtx/sys/sys/syscall.mk --- src.fbsd11.stock/sys/sys/syscall.mk 2016-09-28 19:24:41.000000000 -0400 +++ src.oldumtx/sys/sys/syscall.mk 2017-04-05 15:44:29.738095000 -0400 @@ -1,7 +1,7 @@ # FreeBSD system call object files. # DO NOT EDIT-- this file is automatically generated. -# $FreeBSD: releng/11.0/sys/sys/syscall.mk 303858 2016-08-08 21:19:57Z bdrewery $ -# created from FreeBSD: stable/11/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery +# $FreeBSD$ +# created from FreeBSD: releng/11.0/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery MIASM = \ syscall.o \ exit.o \ @@ -289,6 +289,8 @@ thr_exit.o \ thr_self.o \ thr_kill.o \ + _umtx_lock.o \ + _umtx_unlock.o \ jail_attach.o \ extattr_list_fd.o \ extattr_list_file.o \ diff -u -r src.fbsd11.stock/sys/sys/sysproto.h src.oldumtx/sys/sys/sysproto.h --- src.fbsd11.stock/sys/sys/sysproto.h 2016-09-28 19:24:41.000000000 -0400 +++ src.oldumtx/sys/sys/sysproto.h 2017-04-05 15:44:29.741627000 -0400 @@ -2,8 +2,8 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: releng/11.0/sys/sys/sysproto.h 303858 2016-08-08 21:19:57Z bdrewery $ - * created from FreeBSD: stable/11/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery + * $FreeBSD$ + * created from FreeBSD: releng/11.0/sys/kern/syscalls.master 303854 2016-08-08 20:23:11Z bdrewery */ #ifndef _SYS_SYSPROTO_H_ @@ -1250,6 +1250,12 @@ char id_l_[PADL_(long)]; long id; char id_r_[PADR_(long)]; char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; }; +struct _umtx_lock_args { + char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)]; +}; +struct _umtx_unlock_args { + char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)]; +}; struct jail_attach_args { char jid_l_[PADL_(int)]; int jid; char jid_r_[PADR_(int)]; }; @@ -2067,6 +2073,8 @@ int sys_thr_exit(struct thread *, struct thr_exit_args *); int sys_thr_self(struct thread *, struct thr_self_args *); int sys_thr_kill(struct thread *, struct thr_kill_args *); +int sys__umtx_lock(struct thread *, struct _umtx_lock_args *); +int sys__umtx_unlock(struct thread *, struct _umtx_unlock_args *); int sys_jail_attach(struct thread *, struct jail_attach_args *); int sys_extattr_list_fd(struct thread *, struct extattr_list_fd_args *); int sys_extattr_list_file(struct thread *, struct extattr_list_file_args *); @@ -2844,6 +2852,8 @@ #define SYS_AUE_thr_exit AUE_NULL #define SYS_AUE_thr_self AUE_NULL #define SYS_AUE_thr_kill AUE_NULL +#define SYS_AUE__umtx_lock AUE_NULL +#define SYS_AUE__umtx_unlock AUE_NULL #define SYS_AUE_jail_attach AUE_NULL #define SYS_AUE_extattr_list_fd AUE_EXTATTR_LIST_FD #define SYS_AUE_extattr_list_file AUE_EXTATTR_LIST_FILE diff -u -r src.fbsd11.stock/sys/sys/umtx.h src.oldumtx/sys/sys/umtx.h --- src.fbsd11.stock/sys/sys/umtx.h 2016-09-28 19:24:41.000000000 -0400 +++ src.oldumtx/sys/sys/umtx.h 2017-04-05 17:10:53.884429000 -0400 @@ -31,11 +31,16 @@ #define _SYS_UMTX_H_ #include <sys/_umtx.h> +#include <sys/limits.h> + +#define UMTX_UNOWNED 0x0 +#define UMTX_CONTESTED LONG_MIN /* Common lock flags */ #define USYNC_PROCESS_SHARED 0x0001 /* Process shared sync objs */ /* umutex flags */ +#define UMUTEX_ERROR_CHECK 0x0002 /* Error-checking mutex */ #define UMUTEX_PRIO_INHERIT 0x0004 /* Priority inherited mutex */ #define UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */ #define UMUTEX_ROBUST 0x0010 /* Robust mutex */ @@ -71,8 +76,8 @@ #define USEM_COUNT(c) ((c) & USEM_MAX_COUNT) /* op code for _umtx_op */ -#define UMTX_OP_RESERVED0 0 -#define UMTX_OP_RESERVED1 1 +#define UMTX_OP_LOCK 0 +#define UMTX_OP_UNLOCK 1 #define UMTX_OP_WAIT 2 #define UMTX_OP_WAKE 3 #define UMTX_OP_MUTEX_TRYLOCK 4 @@ -124,6 +129,88 @@ int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2); +/* + * Old (deprecated) userland mutex system calls. + */ +int _umtx_lock(struct umtx *mtx); +int _umtx_unlock(struct umtx *mtx); + +/* + * Standard api. Try uncontested acquire/release and asks the + * kernel to resolve failures. + */ +static __inline void +umtx_init(struct umtx *umtx) +{ + umtx->u_owner = UMTX_UNOWNED; +} + +static __inline u_long +umtx_owner(struct umtx *umtx) +{ + return (umtx->u_owner & ~LONG_MIN); +} + +static __inline int +umtx_lock(struct umtx *umtx, u_long id) +{ + if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0) + if (_umtx_lock(umtx) == -1) + /* return (errno); */ + return (88); /*TODO: Fix all these returns once I know what I'm doing*/ + return (0); +} + +static __inline int +umtx_trylock(struct umtx *umtx, u_long id) +{ + if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0) + /* return (EBUSY); */ + return (16); + return (0); +} + +static __inline int +umtx_timedlock(struct umtx *umtx, u_long id, const struct timespec *timeout) +{ + if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0) + if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, + __DECONST(void *, timeout)) == -1) + /*return (errno); */ + return (88); + return (0); +} + +static __inline int +umtx_unlock(struct umtx *umtx, u_long id) +{ + if (atomic_cmpset_rel_long(&umtx->u_owner, id, UMTX_UNOWNED) == 0) + if (_umtx_unlock(umtx) == -1) + /* return (errno); */ + return (88); + return (0); +} + +static __inline int +umtx_wait(u_long *p, long val, const struct timespec *timeout) +{ + if (_umtx_op(p, UMTX_OP_WAIT, val, 0, + __DECONST(void *, timeout)) == -1) + /* return (errno); */ + return (88); + return (0); +} + +/* Wake threads waiting on a user address. */ +static __inline int +umtx_wake(u_long *p, int nr_wakeup) +{ + if (_umtx_op(p, UMTX_OP_WAKE, nr_wakeup, 0, 0) == -1) + /* return (errno); */ + return (88); + return (0); +} + #else /* diff -u -r src.fbsd11.stock/usr.bin/truss/syscall.h src.oldumtx/usr.bin/truss/syscall.h --- src.fbsd11.stock/usr.bin/truss/syscall.h 2016-09-28 19:26:03.000000000 -0400 +++ src.oldumtx/usr.bin/truss/syscall.h 2017-04-04 14:45:02.960814000 -0400 @@ -23,6 +23,7 @@ * Pollfd -- a pointer to an array of struct pollfd. Prints .fd and .events. * Fd_set -- a pointer to an array of fd_set. Prints the fds that are set. * Sigaction -- a pointer to a struct sigaction. Prints all elements. + * Umtx -- a pointer to a struct umtx. Prints the value of owner. * Sigset -- a pointer to a sigset_t. Prints the signals that are set. * Sigprocmask -- the first argument to sigprocmask(). Prints the name. * Kevent -- a pointer to an array of struct kevents. Prints all elements. @@ -40,7 +41,7 @@ enum Argtype { None = 1, Hex, Octal, Int, UInt, LongHex, Name, Ptr, Stat, Ioctl, Quad, Signal, Sockaddr, StringArray, Timespec, Timeval, Itimerval, Pollfd, Fd_set, Sigaction, Fcntl, Mprot, Mmapflags, Whence, Readlinkres, - Sigset, Sigprocmask, StatFs, Kevent, Sockdomain, Socktype, Open, + Umtx, Sigset, Sigprocmask, StatFs, Kevent, Sockdomain, Socktype, Open, Fcntlflag, Rusage, BinString, Shutdown, Resource, Rlimit, Timeval2, Pathconf, Rforkflags, ExitStatus, Waitoptions, Idtype, Procctl, LinuxSockArgs, Umtxop, Atfd, Atflags, Timespec2, Accessmode, Long, diff -u -r src.fbsd11.stock/usr.bin/truss/syscalls.c src.oldumtx/usr.bin/truss/syscalls.c --- src.fbsd11.stock/usr.bin/truss/syscalls.c 2016-09-28 19:26:03.000000000 -0400 +++ src.oldumtx/usr.bin/truss/syscalls.c 2017-04-04 14:46:19.634451000 -0400 @@ -187,6 +187,10 @@ { .name = "kevent", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } }, + { .name = "_umtx_lock", .ret_type = 0, .nargs = 1, + .args = { { Umtx, 0 } } }, + { .name = "_umtx_unlock", .ret_type = 0, .nargs = 1, + .args = { { Umtx, 0 } } }, { .name = "kill", .ret_type = 1, .nargs = 2, .args = { { Int | IN, 0 }, { Signal | IN, 1 } } }, { .name = "kldfind", .ret_type = 1, .nargs = 1, @@ -668,7 +672,7 @@ }; static struct xlat umtx_ops[] = { - X(UMTX_OP_RESERVED0) X(UMTX_OP_RESERVED1) X(UMTX_OP_WAIT) + X(UMTX_OP_LOCK) X(UMTX_OP_UNLOCK) X(UMTX_OP_WAIT) X(UMTX_OP_WAKE) X(UMTX_OP_MUTEX_TRYLOCK) X(UMTX_OP_MUTEX_LOCK) X(UMTX_OP_MUTEX_UNLOCK) X(UMTX_OP_SET_CEILING) X(UMTX_OP_CV_WAIT) X(UMTX_OP_CV_SIGNAL) X(UMTX_OP_CV_BROADCAST) X(UMTX_OP_WAIT_UINT) @@ -1329,6 +1333,15 @@ } break; } + case Umtx: { + struct umtx umtx; + if (get_struct(pid, (void *)args[sc->offset], &umtx, + sizeof(umtx)) != -1) + asprintf(&tmp, "{ 0x%lx }", (long)umtx.u_owner); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } case Timespec: { struct timespec ts;
Rather than adding backwards compatibility for a 10-year obsolete version of FreeBSD to 11, why not just rebuild jdk1.5.0?
It isn't practical to recompile the jdk in this environment due to its location on a shared filesystem (with a bunch of other stuff) and need to be able to continue running the 8.2 systems as I do the upgrades (a multi-stage process that happens over a period of months, during which work must go on). I started working in this freebsd environment back when it was running 4.8, and the binary compatibility has been a major selling point of FreeBSD through upgrades since then (though my regression tests don't cover product versions from that long ago - iirc we don't need it _quite_ that far back). Being able to replace the environment with new systems that can still run the old toolchains keeps me from having to keep and support my current set of 8.2 servers for X more years (they're too old as it is - ironically one of the reasons I could finally justify upgrading is the need to run a _new_ jdk).
You could rebuild jdk1.5.0 on your 8.2 machines, which have the new interface, and share it with the 11 machines. FreeBSD supports a lot of backwards compatibility but a decade old obsolete interface is expecting a lot.
Most of the time, freebsd6 compatibility is left in. It seems inconsistent to remove the old umtx calls if the rest is left in. It does look unfortunate to have two copies of almost-but-not-completely duplicate code added to kern_umtx.c. However, it may be the least bad way so that development of the current code is hindered as little as possible. Adding the syscall stubs and exports back to libc seems unnecessary since these calls were not supposed to be used by applications directly, and mixing libc/libthr versions is not supported. Likewise, what was removed from <sys/umtx.h> need not be restored (except as needed for kernel implementation). UMUTEX_ERROR_CHECK was added after stable/6 and never used, so need not be restored either. If the old code is dynamically linked, it is worth a try to run it with the new libc and libthr.
Thanks for the pointer - it looks like my binary is dynamically linked, so I'll try making another patch in the next day or so and see if that will work.
I believe I have a new patch, with the syscalls marked as COMPAT6 instead of STD, and without the libc changes, and my test case binary seems to work! On the UMUTEX_ERROR_CHECK definition - on my 8.2-RELEASE systems, it looks like it is being used in error handling for the functions in kern/kern_umtx.c, so I don't think I should get rid of it. I could try and remove it, or does that mean it should be marked compat8 instead of compat6?
I have the same problem running a FreeBSD 6 version of MySQL 4.0.27. This is an application that we just need to keep running in "read only mode" for a possible tax audit - our former years old ERP system. While the mysqld does run, it clogs 1 CPU core 100%. _umtx_op(0x812a10,UMTX_OP_RESERVED0,0x1962b,0x0,0x0) ERR#45 'Operation not supported' _umtx_op(0x812a10,UMTX_OP_RESERVED0,0x1962b,0x0,0x0) ERR#45 'Operation not supported' _umtx_op(0x812a10,UMTX_OP_RESERVED0,0x1962b,0x0,0x0) ERR#45 'Operation not supported' _umtx_op(0x812a10,UMTX_OP_RESERVED0,0x1962b,0x0,0x0) ERR#45 'Operation not supported' _umtx_op(0x812a10,UMTX_OP_RESERVED0,0x1962b,0x0,0x0) ERR#45 'Operation not supported' _umtx_op(0x812a10,UMTX_OP_RESERVED0,0x1962b,0x0,0x0) ERR#45 'Operation not supported' If we have something like COMPAT_FREEBSD6 as a supported feature, why are parts of syscalls removed? FreeBSD 12.2 for me - I threw the entire legacy database server in a jail. Which works apart from the CPU usage. Kind regards, Patrick
Works as expected in FreeBSD 10.4 - so the removal of these two operations is definitely to blame.
Test https://reviews.freebsd.org/D31220
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=9b6b793bd79521edc082a89b264a30881cb65e22 commit 9b6b793bd79521edc082a89b264a30881cb65e22 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-07-19 15:40:38 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-07-28 10:21:12 +0000 Revert most of ce42e793100b460f597e4c85ec0da12e274f9394 to restore ABI compatibility for pre-10.x binaries. It restores _umtx_lock() and _umtx_unlock() syscalls, and UMTX_OP_LOCK/ UMTX_OP_UNLOCK umtx_op(2) operations. UMUTEX_ERROR_CHECK flag is left out for now, I do not think it makes a difference. PR: 218571 Reviewed by: brooks (previous version) Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D31220 sys/compat/freebsd32/syscalls.master | 6 +- sys/kern/kern_umtx.c | 446 ++++++++++++++++++++++++++++++++++- sys/kern/syscalls.master | 14 +- sys/sys/_umtx.h | 4 + sys/sys/umtx.h | 7 +- 5 files changed, 467 insertions(+), 10 deletions(-)
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=2fb281fa02d34b31b25e949415cfda4549b5aa6b commit 2fb281fa02d34b31b25e949415cfda4549b5aa6b Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-07-19 15:40:38 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-08-03 09:52:36 +0000 Revert most of ce42e793100b460f597e4c85ec0da12e274f9394 to restore ABI compatibility for pre-10.x binaries. It restores _umtx_lock() and _umtx_unlock() syscalls, and UMTX_OP_LOCK/ UMTX_OP_UNLOCK umtx_op(2) operations. UMUTEX_ERROR_CHECK flag is left out for now, I do not think it makes a difference. PR: 218571 Reviewed by: brooks (previous version) Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D31220 (cherry picked from commit 9b6b793bd79521edc082a89b264a30881cb65e22) sys/compat/freebsd32/syscalls.master | 6 +- sys/kern/kern_umtx.c | 446 ++++++++++++++++++++++++++++++++++- sys/kern/syscalls.master | 14 +- sys/sys/_umtx.h | 4 + sys/sys/umtx.h | 7 +- 5 files changed, 467 insertions(+), 10 deletions(-)
I guess someone with the necessary superpowers should close this. Correct? Kind regards, Patrick