[Bug 218571] umtx compat6 regression affecting 'jar' command

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Tue Apr 11 21:26:35 UTC 2017


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=218571

            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 at FreeBSD.org
          Reporter: nicholas.hardison at 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 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;

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list