From owner-freebsd-bugs@freebsd.org Tue Apr 11 21:26:34 2017 Return-Path: Delivered-To: freebsd-bugs@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DE192D3A027 for ; Tue, 11 Apr 2017 21:26:34 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2001:1900:2254:206a::16:76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CD376BC3 for ; Tue, 11 Apr 2017 21:26:34 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from bugs.freebsd.org ([127.0.1.118]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id v3BLQY7G083774 for ; Tue, 11 Apr 2017 21:26:34 GMT (envelope-from bugzilla-noreply@freebsd.org) From: bugzilla-noreply@freebsd.org To: freebsd-bugs@FreeBSD.org Subject: [Bug 218571] umtx compat6 regression affecting 'jar' command Date: Tue, 11 Apr 2017 21:26:34 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: kern X-Bugzilla-Version: 11.0-RELEASE X-Bugzilla-Keywords: X-Bugzilla-Severity: Affects Some People X-Bugzilla-Who: nicholas.hardison@gmail.com X-Bugzilla-Status: New X-Bugzilla-Resolution: X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: freebsd-bugs@FreeBSD.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status bug_severity priority component assigned_to reporter Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Apr 2017 21:26:35 -0000 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D218571 Bug ID: 218571 Summary: umtx compat6 regression affecting 'jar' command Product: Base System Version: 11.0-RELEASE Hardware: amd64 OS: Any Status: New Severity: Affects Some People Priority: --- Component: kern Assignee: freebsd-bugs@FreeBSD.org Reporter: nicholas.hardison@gmail.com 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 b= uilt on 6.3-RELEASE I believe), which goes into a loop and hangs. Replicating i= t 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 rem= oved in https://svnweb.freebsd.org/base?view=3Drevision&revision=3D263318 and https://svnweb.freebsd.org/base?view=3Drevision&revision=3D304525. 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 f= ix the jar issue. Looking through the rest of the code, it feels to me like t= he 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 approa= ch 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.0000000= 00 -0400 +++ src.oldumtx/lib/libc/sys/Symbol.map 2017-04-05 13:54:37.026112000 -0= 400 @@ -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 30= 2094 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 timesp= ec32 * abstime; char abstime_r_[PADR_(const struct timespec32 *)]; @@ -757,6 +763,8 @@ int freebsd32_getcontext(struct thread *, struct freebsd32_getcontext_a= rgs *); int freebsd32_setcontext(struct thread *, struct freebsd32_setcontext_a= rgs *); 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 30= 2094 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 30= 2094 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[] =3D { @@ -444,8 +444,8 @@ "thr_exit", /* 431 =3D thr_exit */ "thr_self", /* 432 =3D thr_self */ "thr_kill", /* 433 =3D thr_kill */ - "#434", /* 434 =3D nosys */ - "#435", /* 435 =3D nosys */ + "freebsd32_umtx_lock", /* 434 =3D freebsd32_umtx_lock */ + "freebsd32_umtx_unlock", /* 435 =3D freebsd32_umtx_unlock */ "jail_attach", /* 436 =3D jail_attach */ "extattr_list_fd", /* 437 =3D extattr_list_fd */ "extattr_list_file", /* 438 =3D 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 30= 2094 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 =3D thr_exit */ { AS(thr_self_args), (sy_call_t *)sys_thr_self, AUE_NULL, NULL, 0, 0, = 0, SY_THR_STATIC }, /* 432 =3D thr_self */ { AS(thr_kill_args), (sy_call_t *)sys_thr_kill, AUE_NULL, NULL, 0, 0, = 0, SY_THR_STATIC }, /* 433 =3D thr_kill */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },=20= =20=20=20=20=20=20=20 /* 434 =3D nosys */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },=20= =20=20=20=20=20=20=20 /* 435 =3D nosys */ + { AS(freebsd32_umtx_lock_args), (sy_call_t *)freebsd32_umtx_lock, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 434 =3D freebsd32_umtx_lock= */ + { AS(freebsd32_umtx_unlock_args), (sy_call_t *)freebsd32_umtx_unlock, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 435 =3D freebsd32_umtx_unlo= ck */ { AS(jail_attach_args), (sy_call_t *)sys_jail_attach, AUE_NULL, NULL, = 0, 0, 0, SY_THR_STATIC }, /* 436 =3D 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 =3D 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 =3D 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=20=20=20 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 30= 2095 2016-06-22 21:18:19Z brooks $ + * $FreeBSD$ * This file is part of the DTrace syscall provider. */ @@ -2200,6 +2200,20 @@ *n_args =3D 2; break; } + /* freebsd32_umtx_lock */ + case 434: { + struct freebsd32_umtx_lock_args *p =3D params; + uarg[0] =3D (intptr_t) p->umtx; /* struct umtx * */ + *n_args =3D 1; + break; + } + /* freebsd32_umtx_unlock */ + case 435: { + struct freebsd32_umtx_unlock_args *p =3D params; + uarg[0] =3D (intptr_t) p->umtx; /* struct umtx * */ + *n_args =3D 1; + break; + } /* jail_attach */ case 436: { struct jail_attach_args *p =3D params; @@ -6866,6 +6880,26 @@ break; }; break; + /* freebsd32_umtx_lock */ + case 434: + switch(ndx) { + case 0: + p =3D "struct umtx *"; + break; + default: + break; + }; + break; + /* freebsd32_umtx_unlock */ + case 435: + switch(ndx) { + case 0: + p =3D "struct umtx *"; + break; + default: + break; + }; + break; /* jail_attach */ case 436: switch(ndx) { @@ -10189,6 +10223,16 @@ if (ndx =3D=3D 0 || ndx =3D=3D 1) p =3D "int"; break; + /* freebsd32_umtx_lock */ + case 434: + if (ndx =3D=3D 0 || ndx =3D=3D 1) + p =3D "int"; + break; + /* freebsd32_umtx_unlock */ + case 435: + if (ndx =3D=3D 0 || ndx =3D=3D 1) + p =3D "int"; + break; /* jail_attach */ case 436: if (ndx =3D=3D 0 || ndx =3D=3D 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 -04= 00 @@ -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 =3D thr_exit */ { AS(thr_self_args), (sy_call_t *)sys_thr_self, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 432 =3D thr_self */ { AS(thr_kill_args), (sy_call_t *)sys_thr_kill, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 433 =3D thr_kill */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },=20= =20=20=20=20=20=20=20 /* 434 =3D nosys */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },=20= =20=20=20=20=20=20=20 /* 435 =3D nosys */ + { AS(_umtx_lock_args), (sy_call_t *)sys__umtx_lock, AUE_NULL, NULL, 0,= 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 434 =3D _umtx_lock */ + { AS(_umtx_unlock_args), (sy_call_t *)sys__umtx_unlock, AUE_NULL, NULL= , 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 435 =3D _umtx_unlock */ { AS(jail_attach_args), (sy_call_t *)sys_jail_attach, AUE_NULL, NULL, = 0, 0, 0, SY_THR_STATIC }, /* 436 =3D 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= =3D 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 =3D 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 =3D 0; + + uq =3D td->td_umtxq; + if (timeout !=3D 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 =3D casuword(&umtx->u_owner, UMTX_UNOWNED, id); + + /* The acquire succeeded. */ + if (owner =3D=3D UMTX_UNOWNED) + return (0); + + /* The address was invalid. */ + if (owner =3D=3D -1) + return (EFAULT); + + /* If no one owns it but it is contested try to acquire it. */ + if (owner =3D=3D UMTX_CONTESTED) { + owner =3D casuword(&umtx->u_owner, + UMTX_CONTESTED, id | UMTX_CONTESTED); + + if (owner =3D=3D UMTX_CONTESTED) + return (0); + + /* The address was invalid. */ + if (owner =3D=3D -1) + return (EFAULT); + + error =3D umtxq_check_susp(td); + if (error !=3D 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 !=3D 0) + break; + + if ((error =3D umtx_key_get(umtx, TYPE_SIMPLE_LOCK, + AUTO_SHARE, &uq->uq_key)) !=3D 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 =3D casuword(&umtx->u_owner, owner, owner | UMTX_CONTESTED); + + /* The address was invalid. */ + if (old =3D=3D -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 =3D=3D owner) + error =3D umtxq_sleep(uq, "umtx", timeout =3D=3D NULL ? NULL : + &timo); + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + + if (error =3D=3D 0) + error =3D umtxq_check_susp(td); + } + + if (timeout =3D=3D NULL) { + /* Mutex locking is restarted if it is interrupted. */ + if (error =3D=3D EINTR) + error =3D ERESTART; + } else { + /* Timed-locking is not restarted. */ + if (error =3D=3D ERESTART) + error =3D 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 =3D fuword(__DEVOLATILE(u_long *, &umtx->u_owner)); + if (owner =3D=3D -1) + return (EFAULT); + + if ((owner & ~UMTX_CONTESTED) !=3D id) + return (EPERM); + + /* This should be done in userland */ + if ((owner & UMTX_CONTESTED) =3D=3D 0) { + old =3D casuword(&umtx->u_owner, owner, UMTX_UNOWNED); + if (old =3D=3D -1) + return (EFAULT); + if (old =3D=3D owner) + return (0); + owner =3D old; + } + + /* We should only ever be in here for contested locks */ + if ((error =3D umtx_key_get(umtx, TYPE_SIMPLE_LOCK, AUTO_SHARE, + &key)) !=3D 0) + return (error); + + umtxq_lock(&key); + umtxq_busy(&key); + count =3D 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 =3D casuword(&umtx->u_owner, owner, + count <=3D 1 ? UMTX_UNOWNED : UMTX_CONTESTED); + umtxq_lock(&key); + umtxq_signal(&key,1); + umtxq_unbusy(&key); + umtxq_unlock(&key); + umtx_key_release(&key); + if (old =3D=3D -1) + return (EFAULT); + if (old !=3D 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 =3D 0; + + uq =3D td->td_umtxq; + + if (timeout !=3D 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 =3D casuword32(m, UMUTEX_UNOWNED, id); + + /* The acquire succeeded. */ + if (owner =3D=3D UMUTEX_UNOWNED) + return (0); + + /* The address was invalid. */ + if (owner =3D=3D -1) + return (EFAULT); + + /* If no one owns it but it is contested try to acquire it. */ + if (owner =3D=3D UMUTEX_CONTESTED) { + owner =3D casuword32(m, + UMUTEX_CONTESTED, id | UMUTEX_CONTESTED); + if (owner =3D=3D UMUTEX_CONTESTED) + return (0); + + /* The address was invalid. */ + if (owner =3D=3D -1) + return (EFAULT); + + error =3D umtxq_check_susp(td); + if (error !=3D 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 !=3D 0) + return (error); + + if ((error =3D umtx_key_get(m, TYPE_SIMPLE_LOCK, + AUTO_SHARE, &uq->uq_key)) !=3D 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 =3D casuword32(m, owner, owner | UMUTEX_CONTESTED); + + /* The address was invalid. */ + if (old =3D=3D -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 =3D=3D owner) + error =3D umtxq_sleep(uq, "umtx", timeout =3D=3D NULL ? + NULL : &timo); + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + + if (error =3D=3D 0) + error =3D umtxq_check_susp(td); + } + + if (timeout =3D=3D NULL) { + /* Mutex locking is restarted if it is interrupted. */ + if (error =3D=3D EINTR) + error =3D ERESTART; + } else { + /* Timed-locking is not restarted. */ + if (error =3D=3D ERESTART) + error =3D 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 =3D fuword32(m); + if (owner =3D=3D -1) + return (EFAULT); + + if ((owner & ~UMUTEX_CONTESTED) !=3D id) + return (EPERM); + + /* This should be done in userland */ + if ((owner & UMUTEX_CONTESTED) =3D=3D 0) { + old =3D casuword32(m, owner, UMUTEX_UNOWNED); + if (old =3D=3D -1) + return (EFAULT); + if (old =3D=3D owner) + return (0); + owner =3D old; + } + + /* We should only ever be in here for contested locks */ + if ((error =3D umtx_key_get(m, TYPE_SIMPLE_LOCK, AUTO_SHARE, + &key)) !=3D 0) + return (error); + + umtxq_lock(&key); + umtxq_busy(&key); + count =3D 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 =3D casuword32(m, owner, + count <=3D 1 ? UMUTEX_UNOWNED : UMUTEX_CONTESTED); + umtxq_lock(&key); + umtxq_signal(&key,1); + umtxq_unbusy(&key); + umtxq_unlock(&key); + umtx_key_release(&key); + if (old =3D=3D -1) + return (EFAULT); + if (old !=3D 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) !=3D 0 && + (owner & ~UMUTEX_CONTESTED) =3D=3D id) + return (EDEADLK); + if (mode =3D=3D _UMUTEX_TRY) return (EBUSY); @@ -1880,6 +2245,12 @@ break; } + if ((flags & UMUTEX_ERROR_CHECK) !=3D 0 && + (owner & ~UMUTEX_CONTESTED) =3D=3D id) { + error =3D EDEADLK; + break; + } + if (try !=3D 0) { error =3D EBUSY; break; @@ -2149,6 +2520,12 @@ break; } + if ((flags & UMUTEX_ERROR_CHECK) !=3D 0 && + (owner & ~UMUTEX_CONTESTED) =3D=3D id) { + error =3D EDEADLK; + break; + } + if (try !=3D 0) { error =3D 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 =3D=3D NULL) + ts =3D NULL; + else { + error =3D umtx_copyin_timeout(uap->uaddr2, &timeout); + if (error !=3D 0) + return (error); + ts =3D &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[] =3D { - [UMTX_OP_RESERVED0] =3D __umtx_op_unimpl, - [UMTX_OP_RESERVED1] =3D __umtx_op_unimpl, + [UMTX_OP_LOCK] =3D __umtx_op_lock_umtx, + [UMTX_OP_UNLOCK] =3D __umtx_op_unlock_umtx, [UMTX_OP_WAIT] =3D __umtx_op_wait, [UMTX_OP_WAKE] =3D __umtx_op_wake, [UMTX_OP_MUTEX_TRYLOCK] =3D __umtx_op_trylock_umutex, @@ -3970,6 +4378,19 @@ } #ifdef COMPAT_FREEBSD32 +int +freebsd32_umtx_lock(struct thread *td, struct freebsd32_umtx_lock_args *ua= p) + /* 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 =3D=3D NULL) + ts =3D NULL; + else { + error =3D umtx_copyin_timeout32(uap->uaddr2, &timeout); + if (error !=3D 0) + return (error); + ts =3D &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 *ua= p) +{ + 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[] =3D { - [UMTX_OP_RESERVED0] =3D __umtx_op_unimpl, - [UMTX_OP_RESERVED1] =3D __umtx_op_unimpl, + [UMTX_OP_LOCK] =3D __umtx_op_lock_umtx_compat32, + [UMTX_OP_UNLOCK] =3D __umtx_op_unlock_umtx_compat32, [UMTX_OP_WAIT] =3D __umtx_op_wait_compat32, [UMTX_OP_WAKE] =3D __umtx_op_wake, [UMTX_OP_MUTEX_TRYLOCK] =3D __umtx_op_trylock_umutex, diff -u -r src.fbsd11.stock/sys/kern/syscalls.c src.oldumtx/sys/kern/syscal= ls.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[] =3D { @@ -441,8 +441,8 @@ "thr_exit", /* 431 =3D thr_exit */ "thr_self", /* 432 =3D thr_self */ "thr_kill", /* 433 =3D thr_kill */ - "#434", /* 434 =3D nosys */ - "#435", /* 435 =3D nosys */ + "_umtx_lock", /* 434 =3D _umtx_lock */ + "_umtx_unlock", /* 435 =3D _umtx_unlock */ "jail_attach", /* 436 =3D jail_attach */ "extattr_list_fd", /* 437 =3D extattr_list_fd */ "extattr_list_file", /* 438 =3D 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.000000= 000 -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.000000= 000 -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 =3D 2; break; } + /* _umtx_lock */ + case 434: { + struct _umtx_lock_args *p =3D params; + uarg[0] =3D (intptr_t) p->umtx; /* struct umtx * */ + *n_args =3D 1; + break; + } + /* _umtx_unlock */ + case 435: { + struct _umtx_unlock_args *p =3D params; + uarg[0] =3D (intptr_t) p->umtx; /* struct umtx * */ + *n_args =3D 1; + break; + } /* jail_attach */ case 436: { struct jail_attach_args *p =3D params; @@ -7148,6 +7162,26 @@ break; }; break; + /* _umtx_lock */ + case 434: + switch(ndx) { + case 0: + p =3D "struct umtx *"; + break; + default: + break; + }; + break; + /* _umtx_unlock */ + case 435: + switch(ndx) { + case 0: + p =3D "struct umtx *"; + break; + default: + break; + }; + break; /* jail_attach */ case 436: switch(ndx) { @@ -10246,6 +10280,16 @@ if (ndx =3D=3D 0 || ndx =3D=3D 1) p =3D "int"; break; + /* _umtx_lock */ + case 434: + if (ndx =3D=3D 0 || ndx =3D=3D 1) + p =3D "int"; + break; + /* _umtx_unlock */ + case 435: + if (ndx =3D=3D 0 || ndx =3D=3D 1) + p =3D "int"; + break; /* jail_attach */ case 436: if (ndx =3D=3D 0 || ndx =3D=3D 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 #include +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 -04= 00 +++ 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 -0= 400 +++ 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-0= 8-08 20:23:11Z bdrewery MIASM =3D \ 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 -0= 400 +++ 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 +#include + +#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); +/*=20=20=20=20=20 + * Old (deprecated) userland mutex system calls.=20=20=20=20=20 + */=20=20=20=20=20 +int _umtx_lock(struct umtx *mtx);=20=20=20=20=20 +int _umtx_unlock(struct umtx *mtx);=20=20=20=20=20 +=20=20=20=20=20 +/*=20=20=20=20=20 + * Standard api. Try uncontested acquire/release and asks the=20=20=20=20= =20 + * kernel to resolve failures.=20=20=20=20=20 + */=20=20=20=20=20 +static __inline void=20=20=20=20=20 +umtx_init(struct umtx *umtx)=20=20=20=20=20 +{=20=20=20=20=20 + umtx->u_owner =3D UMTX_UNOWNED;=20=20=20=20=20 +}=20=20=20=20=20 +=20=20=20=20=20 +static __inline u_long=20=20=20=20=20 +umtx_owner(struct umtx *umtx)=20=20=20=20=20 +{=20=20=20=20=20 + return (umtx->u_owner & ~LONG_MIN);=20=20=20=20=20 +}=20=20=20=20=20 +=20=20=20=20=20 +static __inline int=20=20=20=20=20 +umtx_lock(struct umtx *umtx, u_long id)=20=20=20=20=20 +{=20=20=20=20=20 + if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) =3D= =3D 0)=20=20=20=20=20 + if (_umtx_lock(umtx) =3D=3D -1)=20=20=20=20=20 + /* return (errno); */ + return (88); /*TODO: Fix all these returns once I know what I'm doing*/ + return (0);=20=20=20=20=20 +}=20=20=20=20=20 +=20=20=20=20=20 +static __inline int=20=20=20=20=20 +umtx_trylock(struct umtx *umtx, u_long id)=20=20=20=20=20 +{=20=20=20=20=20 + if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) =3D= =3D 0)=20=20=20=20=20 + /* return (EBUSY); */ + return (16); + return (0);=20=20=20=20=20 +}=20=20=20=20=20 +=20=20=20=20=20 +static __inline int=20=20=20=20=20 +umtx_timedlock(struct umtx *umtx, u_long id, const struct timespec *timeou= t)=20=20=20 +{=20=20=20=20=20 + if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) =3D= =3D 0)=20=20=20=20=20 + if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0,=20=20=20=20=20 + __DECONST(void *, timeout)) =3D=3D -1)=20=20=20=20=20 + /*return (errno); */ + return (88); + return (0);=20=20=20=20=20 +}=20=20=20=20=20 +=20=20=20=20=20 +static __inline int=20=20=20=20=20 +umtx_unlock(struct umtx *umtx, u_long id)=20=20=20=20=20 +{=20=20=20=20=20 + if (atomic_cmpset_rel_long(&umtx->u_owner, id, UMTX_UNOWNED) =3D= =3D 0)=20=20=20=20=20 + if (_umtx_unlock(umtx) =3D=3D -1)=20=20=20=20=20 + /* return (errno); */ + return (88); + return (0);=20=20=20=20=20 +}=20=20=20=20=20 +=20=20=20=20=20 +static __inline int=20=20=20=20=20 +umtx_wait(u_long *p, long val, const struct timespec *timeout)=20=20=20=20= =20 +{=20=20=20=20=20 + if (_umtx_op(p, UMTX_OP_WAIT, val, 0,=20=20=20=20=20 + __DECONST(void *, timeout)) =3D=3D -1)=20=20=20=20=20 + /* return (errno); */ + return (88); + return (0);=20=20=20=20=20 +}=20=20=20=20=20 +=20=20=20=20=20 +/* Wake threads waiting on a user address. */=20=20=20=20=20 +static __inline int=20=20=20=20=20 +umtx_wake(u_long *p, int nr_wakeup)=20=20=20=20=20 +{=20=20=20=20=20 + if (_umtx_op(p, UMTX_OP_WAKE, nr_wakeup, 0, 0) =3D=3D -1)=20=20=20= =20=20 + /* return (errno); */ + return (88); + return (0);=20=20=20=20=20 +} + #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.0000000= 00 -0400 +++ src.oldumtx/usr.bin/truss/syscall.h 2017-04-04 14:45:02.960814000 -0= 400 @@ -23,6 +23,7 @@ * Pollfd -- a pointer to an array of struct pollfd. Prints .fd and .even= ts. * 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 =3D 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, Readlinkre= s, - 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.000000= 000 -0400 +++ src.oldumtx/usr.bin/truss/syscalls.c 2017-04-04 14:46:19.634451000 -= 0400 @@ -187,6 +187,10 @@ { .name =3D "kevent", .ret_type =3D 1, .nargs =3D 6, .args =3D { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3= }, { Int, 4 }, { Timespec, 5 } } }, + { .name =3D "_umtx_lock", .ret_type =3D 0, .nargs =3D 1,=20=20=20=20=20 + .args =3D { { Umtx, 0 } } },=20=20=20=20=20 + { .name =3D "_umtx_unlock", .ret_type =3D 0, .nargs =3D 1,=20=20=20=20= =20 + .args =3D { { Umtx, 0 } } }, { .name =3D "kill", .ret_type =3D 1, .nargs =3D 2, .args =3D { { Int | IN, 0 }, { Signal | IN, 1 } } }, { .name =3D "kldfind", .ret_type =3D 1, .nargs =3D 1, @@ -668,7 +672,7 @@ }; static struct xlat umtx_ops[] =3D { - 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: {=20=20=20=20=20 + struct umtx umtx; + if (get_struct(pid, (void *)args[sc->offset], &umtx, + sizeof(umtx)) !=3D -1) + asprintf(&tmp, "{ 0x%lx }", (long)umtx.u_owner); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } case Timespec: { struct timespec ts; --=20 You are receiving this mail because: You are the assignee for the bug.=