Module Name:    src
Committed By:   christos
Date:           Sun Jul  3 14:24:59 UTC 2016

Modified Files:
        src/lib/libc/gen: sysconf.3 sysconf.c
        src/lib/libc/sys: Makefile.inc
        src/lib/libpthread: Makefile pthread.h pthread_barrier.3
            pthread_barrier.c pthread_barrierattr.3 pthread_cond.c
            pthread_condattr.3 pthread_mutex.3 pthread_mutex.c
            pthread_mutexattr.3 pthread_rwlock.c pthread_rwlockattr.3
            pthread_types.h
        src/sys/kern: kern_lwp.c kern_sleepq.c kern_synch.c sys_sched.c
            syscalls.master
        src/sys/sys: lwp.h sched.h unistd.h
        src/tests/lib/libpthread: t_cond.c t_mutex.c

Log Message:
GSoC 2016 Charles Cui: Implement thread priority protection based on work
by Andy Doran. Also document the get/set pshared thread calls as not
implemented, and add a skeleton implementation that is disabled.
XXX: document _sched_protect(2).


To generate a diff of this commit:
cvs rdiff -u -r1.48 -r1.49 src/lib/libc/gen/sysconf.3
cvs rdiff -u -r1.39 -r1.40 src/lib/libc/gen/sysconf.c
cvs rdiff -u -r1.230 -r1.231 src/lib/libc/sys/Makefile.inc
cvs rdiff -u -r1.86 -r1.87 src/lib/libpthread/Makefile
cvs rdiff -u -r1.36 -r1.37 src/lib/libpthread/pthread.h
cvs rdiff -u -r1.4 -r1.5 src/lib/libpthread/pthread_barrier.3
cvs rdiff -u -r1.19 -r1.20 src/lib/libpthread/pthread_barrier.c
cvs rdiff -u -r1.9 -r1.10 src/lib/libpthread/pthread_barrierattr.3 \
    src/lib/libpthread/pthread_condattr.3
cvs rdiff -u -r1.63 -r1.64 src/lib/libpthread/pthread_cond.c
cvs rdiff -u -r1.6 -r1.7 src/lib/libpthread/pthread_mutex.3
cvs rdiff -u -r1.59 -r1.60 src/lib/libpthread/pthread_mutex.c
cvs rdiff -u -r1.11 -r1.12 src/lib/libpthread/pthread_mutexattr.3
cvs rdiff -u -r1.33 -r1.34 src/lib/libpthread/pthread_rwlock.c
cvs rdiff -u -r1.8 -r1.9 src/lib/libpthread/pthread_rwlockattr.3
cvs rdiff -u -r1.17 -r1.18 src/lib/libpthread/pthread_types.h
cvs rdiff -u -r1.184 -r1.185 src/sys/kern/kern_lwp.c
cvs rdiff -u -r1.50 -r1.51 src/sys/kern/kern_sleepq.c
cvs rdiff -u -r1.310 -r1.311 src/sys/kern/kern_synch.c
cvs rdiff -u -r1.43 -r1.44 src/sys/kern/sys_sched.c
cvs rdiff -u -r1.284 -r1.285 src/sys/kern/syscalls.master
cvs rdiff -u -r1.171 -r1.172 src/sys/sys/lwp.h
cvs rdiff -u -r1.75 -r1.76 src/sys/sys/sched.h
cvs rdiff -u -r1.58 -r1.59 src/sys/sys/unistd.h
cvs rdiff -u -r1.6 -r1.7 src/tests/lib/libpthread/t_cond.c
cvs rdiff -u -r1.7 -r1.8 src/tests/lib/libpthread/t_mutex.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/gen/sysconf.3
diff -u src/lib/libc/gen/sysconf.3:1.48 src/lib/libc/gen/sysconf.3:1.49
--- src/lib/libc/gen/sysconf.3:1.48	Fri Jun 10 19:29:20 2016
+++ src/lib/libc/gen/sysconf.3	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-.\"	$NetBSD: sysconf.3,v 1.48 2016/06/10 23:29:20 christos Exp $
+.\"	$NetBSD: sysconf.3,v 1.49 2016/07/03 14:24:58 christos Exp $
 .\"
 .\" Copyright (c) 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -178,6 +178,8 @@ and its
 Threads
 option to which the system attempts to conform,
 otherwise \-1.
+.It Li _SC_THREAD_PRIO_PROTECT
+System supports the priority ceiling protocol for POSIX threads.
 .It Li _SC_TIMERS
 The version of
 .St -p1003.1

Index: src/lib/libc/gen/sysconf.c
diff -u src/lib/libc/gen/sysconf.c:1.39 src/lib/libc/gen/sysconf.c:1.40
--- src/lib/libc/gen/sysconf.c:1.39	Fri Jun 10 19:29:20 2016
+++ src/lib/libc/gen/sysconf.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysconf.c,v 1.39 2016/06/10 23:29:20 christos Exp $	*/
+/*	$NetBSD: sysconf.c,v 1.40 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)sysconf.c	8.2 (Berkeley) 3/20/94";
 #else
-__RCSID("$NetBSD: sysconf.c,v 1.39 2016/06/10 23:29:20 christos Exp $");
+__RCSID("$NetBSD: sysconf.c,v 1.40 2016/07/03 14:24:58 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -411,9 +411,10 @@ yesno:		if (sysctl(mib, mib_len, &value,
 		return _POSIX_THREAD_ATTR_STACKSIZE;
 	case _SC_THREAD_SAFE_FUNCTIONS:
 		return _POSIX_THREAD_SAFE_FUNCTIONS;
+	case _SC_THREAD_PRIO_PROTECT:
+		return _POSIX_THREAD_PRIO_PROTECT;
 	case _SC_THREAD_PRIORITY_SCHEDULING:
 	case _SC_THREAD_PRIO_INHERIT:
-	case _SC_THREAD_PRIO_PROTECT:
 	case _SC_THREAD_PROCESS_SHARED:
 		return -1;
 	case _SC_TTY_NAME_MAX:

Index: src/lib/libc/sys/Makefile.inc
diff -u src/lib/libc/sys/Makefile.inc:1.230 src/lib/libc/sys/Makefile.inc:1.231
--- src/lib/libc/sys/Makefile.inc:1.230	Sat Apr 23 19:11:31 2016
+++ src/lib/libc/sys/Makefile.inc	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.230 2016/04/23 23:11:31 christos Exp $
+#	$NetBSD: Makefile.inc,v 1.231 2016/07/03 14:24:58 christos Exp $
 #	@(#)Makefile.inc	8.3 (Berkeley) 10/24/94
 
 # sys sources
@@ -173,7 +173,7 @@ WEAKASM= accept.S __aio_suspend50.S clos
 	msgrcv.S msgsnd.S __msync13.S  __nanosleep50.S open.S poll.S \
 	__pollts50.S __pselect50.S read.S readlink.S \
 	readv.S _sched_setparam.S _sched_getparam.S _sched_setaffinity.S \
-	_sched_getaffinity.S sched_yield.S \
+	_sched_getaffinity.S sched_yield.S _sched_protect.S \
 	__select50.S setcontext.S __sigprocmask14.S __sigsuspend14.S sysarch.S \
 	__wait450.S wait6.S write.S writev.S
 

Index: src/lib/libpthread/Makefile
diff -u src/lib/libpthread/Makefile:1.86 src/lib/libpthread/Makefile:1.87
--- src/lib/libpthread/Makefile:1.86	Sat Apr 23 19:12:19 2016
+++ src/lib/libpthread/Makefile	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.86 2016/04/23 23:12:19 christos Exp $
+#	$NetBSD: Makefile,v 1.87 2016/07/03 14:24:58 christos Exp $
 #
 
 WARNS?=	5
@@ -177,6 +177,8 @@ MLINKS+=	pthread_barrier.3 pthread_barri
 
 MLINKS+=	pthread_barrierattr.3 pthread_barrierattr_init.3
 MLINKS+=	pthread_barrierattr.3 pthread_barrierattr_destroy.3
+MLINKS+=	pthread_barrierattr.3 pthread_barrierattr_getpshared.3
+MLINKS+=	pthread_barrierattr.3 pthread_barrierattr_setpshared.3
 
 MLINKS+=	pthread_cond.3 pthread_cond_init.3
 MLINKS+=	pthread_cond.3 pthread_cond_destroy.3
@@ -188,6 +190,9 @@ MLINKS+=	pthread_cond.3 pthread_cond_tim
 MLINKS+=	pthread_condattr.3 pthread_condattr_init.3
 MLINKS+=	pthread_condattr.3 pthread_condattr_destroy.3
 MLINKS+=	pthread_condattr.3 pthread_condattr_setclock.3
+MLINKS+=	pthread_condattr.3 pthread_condattr_getclock.3
+MLINKS+=	pthread_condattr.3 pthread_condattr_getpshared.3
+MLINKS+=	pthread_condattr.3 pthread_condattr_setpshared.3
 
 MLINKS+=	pthread_getname_np.3 pthread_setname_np.3
 MLINKS+=	pthread_getspecific.3 pthread_setspecific.3
@@ -198,11 +203,20 @@ MLINKS+=	pthread_mutex.3 pthread_mutex_d
 MLINKS+=	pthread_mutex.3 pthread_mutex_lock.3
 MLINKS+=	pthread_mutex.3 pthread_mutex_trylock.3
 MLINKS+=	pthread_mutex.3 pthread_mutex_unlock.3
+MLINKS+=	pthread_mutex.3 pthread_mutex_timedlock.3
+MLINKS+=	pthread_mutex.3	pthread_mutex_getprioceiling.3
+MLINKS+=	pthread_mutex.3	pthread_mutex_setprioceiling.3 
 
 MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_init.3
 MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_destroy.3
+MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_getpshared.3
+MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_setpshared.3
 MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_settype.3
 MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_gettype.3
+MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_getprotocol.3
+MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_setprotocol.3
+MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_getprioceiling.3
+MLINKS+=	pthread_mutexattr.3 pthread_mutexattr_setprioceiling.3	
 
 MLINKS+=	pthread_rwlock.3 pthread_rwlock_init.3
 MLINKS+=	pthread_rwlock.3 pthread_rwlock_destroy.3
@@ -217,6 +231,8 @@ MLINKS+=	pthread_rwlock.3 pthread_rwlock
 
 MLINKS+=	pthread_rwlockattr.3 pthread_rwlockattr_init.3
 MLINKS+=	pthread_rwlockattr.3 pthread_rwlockattr_destroy.3
+MLINKS+=	pthread_rwlockattr.3 pthread_rwlockattr_getpshared.3
+MLINKS+=	pthread_rwlockattr.3 pthread_rwlockattr_setpshared.3
 
 MLINKS+=	pthread_spin.3 pthread_spin_init.3
 MLINKS+=	pthread_spin.3 pthread_spin_destroy.3

Index: src/lib/libpthread/pthread.h
diff -u src/lib/libpthread/pthread.h:1.36 src/lib/libpthread/pthread.h:1.37
--- src/lib/libpthread/pthread.h:1.36	Sat Apr 23 19:12:19 2016
+++ src/lib/libpthread/pthread.h	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread.h,v 1.36 2016/04/23 23:12:19 christos Exp $	*/
+/*	$NetBSD: pthread.h,v 1.37 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -94,12 +94,30 @@ int	pthread_mutex_destroy(pthread_mutex_
 int	pthread_mutex_lock(pthread_mutex_t *);
 int	pthread_mutex_trylock(pthread_mutex_t *);
 int	pthread_mutex_unlock(pthread_mutex_t *);
+int	pthread_mutex_timedlock(pthread_mutex_t *,
+	    const struct timespec * __restrict);
+int	pthread_mutex_getprioceiling(const pthread_mutex_t * __restrict,
+	    int * __restrict);
+int	pthread_mutex_setprioceiling(pthread_mutex_t * __restrict, int,
+	    int * __restrict);
 int	pthread_mutexattr_init(pthread_mutexattr_t *);
 int	pthread_mutexattr_destroy(pthread_mutexattr_t *);
+#ifdef _PTHREAD_PSHARED
+int	pthread_mutexattr_getpshared(const pthread_mutexattr_t * __restrict,
+	    int * __restrict);
+int	pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+#endif
 int	pthread_mutexattr_gettype(const pthread_mutexattr_t * __restrict,
 	    int * __restrict);
 int	pthread_mutexattr_settype(pthread_mutexattr_t *attr, int);
-
+int	pthread_mutexattr_getprotocol(const pthread_mutexattr_t * __restrict,
+	    int * __restrict);
+int	pthread_mutexattr_setprotocol(pthread_mutexattr_t*,
+	    int);
+int	pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * __restrict,
+	    int * __restrict);
+int	pthread_mutexattr_setprioceiling(pthread_mutexattr_t *,
+	    int);
 int	pthread_cond_init(pthread_cond_t * __restrict,
 	    const pthread_condattr_t * __restrict);
 int	pthread_cond_destroy(pthread_cond_t *);
@@ -114,9 +132,15 @@ int	pthread_cond_broadcast(pthread_cond_
 int	pthread_condattr_init(pthread_condattr_t *);
 #if defined(_NETBSD_SOURCE)
 int     pthread_condattr_setclock(pthread_condattr_t *, clockid_t);
+int	pthread_condattr_getclock(const pthread_condattr_t * __restrict,
+	    clockid_t * __restrict);
 #endif
 int	pthread_condattr_destroy(pthread_condattr_t *);
-
+#ifdef _PTHREAD_PSHARED
+int	pthread_condattr_getpshared(const pthread_condattr_t * __restrict,
+	    int * __restrict);
+int	pthread_condattr_setpshared(pthread_condattr_t *, int);
+#endif
 int	pthread_once(pthread_once_t *, void (*)(void));
 
 int	pthread_key_create(pthread_key_t *, void (*)(void *));
@@ -178,14 +202,22 @@ int	pthread_rwlock_timedwrlock(pthread_r
 int	pthread_rwlock_unlock(pthread_rwlock_t *);
 int	pthread_rwlockattr_init(pthread_rwlockattr_t *);
 int	pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
-
+#ifdef _PTHREAD_PSHARED
+int	pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * __restrict,
+	    int * __restrict);
+int	pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
+#endif
 int	pthread_barrier_init(pthread_barrier_t * __restrict,
 	    const pthread_barrierattr_t * __restrict, unsigned int);
 int	pthread_barrier_wait(pthread_barrier_t *);
 int	pthread_barrier_destroy(pthread_barrier_t *);
 int	pthread_barrierattr_init(pthread_barrierattr_t *);
 int	pthread_barrierattr_destroy(pthread_barrierattr_t *);
-
+#ifdef _PTHREAD_PSHARED
+int	pthread_barrierattr_getpshared(const pthread_barrierattr_t * __restrict,
+    int * __restrict);
+int	pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
+#endif
 int	pthread_getschedparam(pthread_t, int * __restrict,
 	    struct sched_param * __restrict);
 int	pthread_setschedparam(pthread_t, int, const struct sched_param *);
@@ -251,6 +283,10 @@ __END_DECLS
 #define	PTHREAD_MUTEX_RECURSIVE		2
 #define	PTHREAD_MUTEX_DEFAULT		PTHREAD_MUTEX_NORMAL
 
+#define	PTHREAD_PRIO_NONE		0
+#define	PTHREAD_PRIO_INHERIT		1
+#define	PTHREAD_PRIO_PROTECT		2
+
 #define PTHREAD_COND_INITIALIZER	_PTHREAD_COND_INITIALIZER
 #define PTHREAD_MUTEX_INITIALIZER	_PTHREAD_MUTEX_INITIALIZER
 #define PTHREAD_ONCE_INIT		_PTHREAD_ONCE_INIT

Index: src/lib/libpthread/pthread_barrier.3
diff -u src/lib/libpthread/pthread_barrier.3:1.4 src/lib/libpthread/pthread_barrier.3:1.5
--- src/lib/libpthread/pthread_barrier.3:1.4	Fri Jul  9 14:07:20 2010
+++ src/lib/libpthread/pthread_barrier.3	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-.\" $NetBSD: pthread_barrier.3,v 1.4 2010/07/09 18:07:20 jruoho Exp $
+.\" $NetBSD: pthread_barrier.3,v 1.5 2016/07/03 14:24:58 christos Exp $
 .\"
 .\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -25,7 +25,8 @@
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\" ----------------------------------------------------------------------------
-.Dd July 8, 2010
+
+.Dd June 12, 2016
 .Dt PTHREAD_BARRIER 3
 .Os
 .Sh NAME
@@ -42,7 +43,14 @@
 .Fn pthread_barrier_destroy "pthread_barrier_t *barrier"
 .Ft int
 .Fn pthread_barrier_wait "pthread_barrier_t *barrier"
+.Ft int
+.Fn pthread_barrierattr_getpshared "const pthread_barrierattr_t * __restrict attr" \
+"int * __restrict pshared"
+.Ft int
+.Fn pthread_barrierattr_setpshared "pthread_barrierattr_t * attr" \
+"int pshared" 
 .\" ----------------------------------------------------------------------------
+
 .Sh DESCRIPTION
 The
 .Fn pthread_barrier_init
@@ -87,7 +95,18 @@ call have called
 all threads will wake up, return from their respective
 .Fn pthread_barrier_wait
 calls and continue execution.
+.Pp
+.\" -----
+The
+.Fn pthread_barrierattr_getpshared 
+function shall obtain the value of the process-shared attribute from the
+attributes object referenced by attr. 
+The
+.Fn pthread_barrierattr_setpshared
+function shall set the process-shared attribute in an initialized attributes
+object referenced by attr. 
 .\" ----------------------------------------------------------------------------
+
 .Sh RETURN VALUES
 If successful,
 .Fn pthread_barrier_init
@@ -113,7 +132,23 @@ It is the responsibility of this thread 
 and atomicity of any updates to shared data with respect to the
 other threads participating in the barrier.
 In the case of failure, an error value will be returned.
+.Pp
+.\" -----
+If successful,
+.Fn pthread_barrierattr_getpshared
+shall return zero and store the value of the process-shared attribute of attr 
+into the object referenced by the
+.Fa pshared
+parameter.
+Otherwise, an error number shall be returned to indicate the error.
+.Pp
+.\" -----
+If successful,
+.Fn pthread_barrierattr_setpshared
+shall return zero;
+Otherwise, an error number shall be returned to indicate the error. 
 .\" ----------------------------------------------------------------------------
+
 .Sh ERRORS
 The
 .Fn pthread_barrier_init
@@ -152,6 +187,20 @@ The value specified by
 .Fa barrier
 is invalid.
 .El
+.Pp
+.\" -----
+The 
+.Fn pthread_barrierattr_setpshared
+function and 
+the
+.Fn pthread_barrierattr_getpshared
+function may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value specified by
+.Fa attr
+is invalid.
+
 .\" ---------------------------------------------------------------------------
 .Sh SEE ALSO
 .Xr pthread_barrierattr 3 ,
@@ -160,3 +209,10 @@ is invalid.
 .Sh STANDARDS
 These functions conform to
 .St -p1003.1-2001 .
+.Sh BUGS
+The
+.Fn pthread_barrierattr_getpshared
+and
+.Fn pthread_barrierattr_setpshared
+functions are hidden by default since only thread shared attributes
+are supported.

Index: src/lib/libpthread/pthread_barrier.c
diff -u src/lib/libpthread/pthread_barrier.c:1.19 src/lib/libpthread/pthread_barrier.c:1.20
--- src/lib/libpthread/pthread_barrier.c:1.19	Thu Jan 29 16:19:35 2009
+++ src/lib/libpthread/pthread_barrier.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread_barrier.c,v 1.19 2009/01/29 21:19:35 ad Exp $	*/
+/*	$NetBSD: pthread_barrier.c,v 1.20 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2003, 2006, 2007, 2009 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_barrier.c,v 1.19 2009/01/29 21:19:35 ad Exp $");
+__RCSID("$NetBSD: pthread_barrier.c,v 1.20 2016/07/03 14:24:58 christos Exp $");
 
 #include <errno.h>
 
@@ -117,6 +117,29 @@ pthread_barrier_wait(pthread_barrier_t *
 	return 0;
 }
 
+#ifdef _PTHREAD_PSHARED
+int
+pthread_barrierattr_getpshared(const pthread_barrierattr_t * __restrict attr,
+    int * __restrict pshared)
+{
+
+	*pshared = PTHREAD_PROCESS_PRIVATE;
+	return 0;
+}
+
+int
+pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared)
+{
+
+	switch(pshared) {
+	case PTHREAD_PROCESS_PRIVATE:
+		return 0;
+	case PTHREAD_PROCESS_SHARED:
+		return ENOSYS;
+	}
+	return EINVAL;
+}
+#endif
 
 int
 pthread_barrierattr_init(pthread_barrierattr_t *attr)

Index: src/lib/libpthread/pthread_barrierattr.3
diff -u src/lib/libpthread/pthread_barrierattr.3:1.9 src/lib/libpthread/pthread_barrierattr.3:1.10
--- src/lib/libpthread/pthread_barrierattr.3:1.9	Fri Jul  9 06:45:36 2010
+++ src/lib/libpthread/pthread_barrierattr.3	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-.\" $NetBSD: pthread_barrierattr.3,v 1.9 2010/07/09 10:45:36 wiz Exp $
+.\" $NetBSD: pthread_barrierattr.3,v 1.10 2016/07/03 14:24:58 christos Exp $
 .\"
 .\" Copyright (c) 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -22,12 +22,14 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd July 9, 2010
+.Dd June 12, 2016
 .Dt PTHREAD_BARRIERATTR 3
 .Os
 .Sh NAME
 .Nm pthread_barrierattr_init ,
 .Nm pthread_barrierattr_destroy ,
+.Nm pthread_barrierattr_getpshared ,
+.Nm pthread_barrierattr_setpshared
 .Nd barrier attribute operations
 .Sh LIBRARY
 .Lb libpthread
@@ -37,6 +39,10 @@
 .Fn pthread_barrierattr_init "pthread_barrierattr_t *attr"
 .Ft int
 .Fn pthread_barrierattr_destroy "pthread_barrierattr_t *attr"
+.Ft int
+.Fn pthread_barrierattr_getpshared "const pthread_barrierattr_t * __restrict attr" "int * __restrict pshared"
+.Ft int
+.Fn pthread_barrierattr_setpshared "pthread_barrierattr_t * attr" "int pshared"
 .Sh DESCRIPTION
 Barrier attributes are used to specify parameters to be used with
 .Xr pthread_barrier_init 3 .
@@ -54,6 +60,19 @@ The
 .Fn pthread_barrierattr_destroy
 function destroys
 .Fa attr .
+.Pp
+The
+.Fn pthread_barrierattr_getpshared
+function shall obtain the value of the process-shared attribute
+from the attributes object referenced by 
+.Fa attr .
+.Pp
+The
+.Fn pthread_barrierattr_setpshared
+function shall set the process-shared attribute in an initialized
+attributes object referenced by 
+.Fa attr .
+
 .Sh RETURN VALUES
 If successful, these functions return 0.
 Otherwise, an error number is returned to indicate the error.
@@ -70,8 +89,27 @@ The value specified by
 .Fa attr
 is invalid.
 .El
+.Pp
+The
+.Fn pthread_barrierattr_getpshared
+and
+.Fn pthread_barrierattr_setpshared
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value specified by
+.Fa attr 
+is invalid.
+.El
 .Sh SEE ALSO
 .Xr pthread_barrier_init 3
 .Sh STANDARDS
 Both functions conform to
 .St -p1003.1-2001 .
+.Sh BUGS
+The
+.Fn pthread_barrierattr_getpshared
+and
+.Fn pthread_barrierattr_setpshared
+functions are hidden by default since only thread shared attributes
+are supported.
Index: src/lib/libpthread/pthread_condattr.3
diff -u src/lib/libpthread/pthread_condattr.3:1.9 src/lib/libpthread/pthread_condattr.3:1.10
--- src/lib/libpthread/pthread_condattr.3:1.9	Sat Nov  3 05:20:36 2012
+++ src/lib/libpthread/pthread_condattr.3	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-.\" $NetBSD: pthread_condattr.3,v 1.9 2012/11/03 09:20:36 wiz Exp $
+.\" $NetBSD: pthread_condattr.3,v 1.10 2016/07/03 14:24:58 christos Exp $
 .\"
 .\" Copyright (c) 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -50,11 +50,15 @@
 .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\" $FreeBSD: src/lib/libpthread/man/pthread_condattr.3,v 1.10 2002/09/16 19:29:28 mini Exp $
-.Dd November 2, 2012
+.Dd June 12, 2016
 .Dt PTHREAD_CONDATTR 3
 .Os
 .Sh NAME
-.Nm pthread_condattr_init
+.Nm pthread_condattr_init, 
+.Nm pthread_condattr_getpshared,
+.Nm pthread_condattr_setpshared,
+.Nm pthread_condattr_getclock,
+.Nm pthread_condattr_setclock
 .Nd condition attribute operations
 .Sh LIBRARY
 .Lb libpthread
@@ -63,9 +67,16 @@
 .Ft int
 .Fn pthread_condattr_init "pthread_condattr_t *attr"
 .Ft int
+.Fn pthread_condattr_getclock "const pthread_condattr_t *__restrict attr" \
+"clockid_t * __restrict clock_id"
+.Ft int
 .Fn pthread_condattr_setclock "pthread_condattr_t *attr" "clockid_t clock"
 .Ft int
 .Fn pthread_condattr_destroy "pthread_condattr_t *attr"
+.Ft int
+.Fn pthread_condattr_getpshared "const pthread_condattr_t * __restrict attr" "int * __restrict pshared"
+.Ft int
+.Fn pshared_condattr_setpshared "pthread_condattr_t *attr" "int pshared"
 .Sh DESCRIPTION
 Condition attribute objects are used to specify parameters to the
 .Xr pthread_cond_init 3
@@ -77,6 +88,12 @@ and the
 .Fn pthread_condattr_destroy
 function destroys a condition attribute object.
 The
+.Fn pthread_condattr_getclock
+function shall obtain the value of the 
+.Fa clock
+attributes object referenced by
+.Fa attr.
+The
 .Fn pthread_condattr_setclock
 function sets the system clock to be used for time comparisons to
 the one specified in
@@ -86,6 +103,16 @@ Valid clock values are
 and
 .Dv CLOCK_REALTIME
 (the default).
+The
+.Fn pthread_condattr_getpshared
+function shall obtain the value of the process-shared attribute from the 
+attributes object referenced by
+.Fa attr.
+The
+.Fn pthread_condattr_setpshared
+function shall set the process-shared attribute in an initialized attributes 
+object referenced by 
+.Fa attr.
 .Sh RETURN VALUES
 If successful, these functions return 0.
 Otherwise, an error number is returned to indicate the error.
@@ -102,6 +129,28 @@ The value specified by
 .Fa attr
 is invalid.
 .El
+.Pp
+The
+.Fn pthread_condattr_getclock 
+and
+.Fn pthread_condattr_setclock
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value specified by
+.Fa attr is invalid.
+.El
+.Pp
+The
+.Fn pthread_condattr_getpshared
+and
+.Fn pthread_condattr_setpshared
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value specified by
+.Fa attr
+is invalid.
 .Sh SEE ALSO
 .Xr pthread_cond_init 3
 .Sh STANDARDS
@@ -115,3 +164,10 @@ These functions do not conform to the
 .St -p1003.1-2008
 revision of the standard, which mandates two additional attributes,
 the clock attribute and the process-shared attribute.
+.Sh BUGS
+The
+.Fn pthread_condattr_getpshared
+and
+.Fn pthread_condattr_setpshared
+functions are hidden by default since only thread shared attributes
+are supported.

Index: src/lib/libpthread/pthread_cond.c
diff -u src/lib/libpthread/pthread_cond.c:1.63 src/lib/libpthread/pthread_cond.c:1.64
--- src/lib/libpthread/pthread_cond.c:1.63	Fri Jan 31 15:44:01 2014
+++ src/lib/libpthread/pthread_cond.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread_cond.c,v 1.63 2014/01/31 20:44:01 christos Exp $	*/
+/*	$NetBSD: pthread_cond.c,v 1.64 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -46,7 +46,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_cond.c,v 1.63 2014/01/31 20:44:01 christos Exp $");
+__RCSID("$NetBSD: pthread_cond.c,v 1.64 2016/07/03 14:24:58 christos Exp $");
 
 #include <stdlib.h>
 #include <errno.h>
@@ -370,6 +370,16 @@ pthread_condattr_setclock(pthread_condat
 }
 
 int
+pthread_condattr_getclock(const pthread_condattr_t *__restrict attr,
+    clockid_t *__restrict clock_id)
+{
+	if (attr == NULL || attr->ptca_private == NULL)
+		return EINVAL;
+	*clock_id = *(clockid_t *)attr->ptca_private;
+	return 0;
+}
+
+int
 pthread_condattr_destroy(pthread_condattr_t *attr)
 {
 
@@ -382,6 +392,30 @@ pthread_condattr_destroy(pthread_condatt
 	return 0;
 }
 
+#ifdef _PTHREAD_PSHARED
+int
+pthread_condattr_getpshared(const pthread_condattr_t * __restrict attr,
+    int * __restrict pshared)
+{
+
+	*pshared = PTHREAD_PROCESS_PRIVATE;
+	return 0;
+}
+
+int
+pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared)
+{
+
+	switch(pshared) {
+	case PTHREAD_PROCESS_PRIVATE:
+		return 0;
+	case PTHREAD_PROCESS_SHARED:
+		return ENOSYS;
+	}
+	return EINVAL;
+}
+#endif
+
 /* Utility routine to hang out for a while if threads haven't started yet. */
 static int
 pthread_cond_wait_nothread(pthread_t self, pthread_mutex_t *mutex,

Index: src/lib/libpthread/pthread_mutex.3
diff -u src/lib/libpthread/pthread_mutex.3:1.6 src/lib/libpthread/pthread_mutex.3:1.7
--- src/lib/libpthread/pthread_mutex.3:1.6	Mon Nov 12 18:11:05 2012
+++ src/lib/libpthread/pthread_mutex.3	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-.\" $NetBSD: pthread_mutex.3,v 1.6 2012/11/12 23:11:05 uwe Exp $
+.\" $NetBSD: pthread_mutex.3,v 1.7 2016/07/03 14:24:58 christos Exp $
 .\"
 .\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -52,7 +52,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" ----------------------------------------------------------------------------
-.Dd July 8, 2010
+.Dd June 12, 2016
 .Dt PTHREAD_MUTEX 3
 .Os
 .Sh NAME
@@ -75,6 +75,14 @@
 .Fn pthread_mutex_trylock "pthread_mutex_t *mutex"
 .Ft int
 .Fn pthread_mutex_unlock "pthread_mutex_t *mutex"
+.Ft int
+.Fn pthread_mutex_timedlock "pthread_mutex_t * mutex" "const struct timespec *__restrict timeout"
+.Ft int
+.Fn pthread_mutex_getprioceiling "const pthread_mutex_t * __restrict mutex" "int * __restrict prioceiling"
+.Ft int
+.Fn pthread_mutex_setprioceiling "pthread_mutex_t * __restrict mutex" \
+"int prioceiling" "int * __restrict old_ceiling"
+
 .\" ----------------------------------------------------------------------------
 .Sh DESCRIPTION
 The
@@ -135,7 +143,45 @@ When operating with the default mutex ty
 undefined behavior follows if a thread tries to unlock a mutex
 that has not been locked by it, or if a thread tries to release
 a mutex that is already unlocked.
+.Pp
+.\" -----
+The 
+.Fn pthread_mutex_timedlock
+function shall lock the mutex object referenced by
+.Fa mutex.
+If the mutex is already locked, the calling thread shall block until
+the mutex becomes available in the 
+.Fn pthread_mutex_lock
+function.
+If the mutex cannot be locked without waiting for another thread to
+unlock the mutex, this wait shall be terminated when the specified timeout
+expires.
+The timeout shall expire when the absolute time specified by 
+.Fa timeout
+passes, as measured by the clock on which timeouts are based.
+.Pp
+.\" -----
+The
+.Fn pthread_mutex_getprioceiling
+function shall return the current priority ceiling of the mutex.
+.Pp
+.\" -----
+The 
+.Fn pthread_mutex_setprioceiling
+function shall either lock the mutex if it is unlocked, or block until
+it can sucessfully lock the mutex, then it shall change the mutex's priority
+ceiling and release the mutex.
+When the change is successful, the previous value of the priority ceiling
+shall be returned
+in
+.Fa old_ceiling.
+The process of locking the mutex need not adhere to the priority
+protect protocol.
+If
+.Fn pthread_mutex_setprioceiling
+function fails, the mutex priority ceiling shall not be changed.
 .\" ----------------------------------------------------------------------------
+
 .Sh RETURN VALUES
 Upon success all described functions return zero.
 Otherwise, an error number will be returned to indicate the error.
@@ -203,7 +249,45 @@ is invalid.
 The current thread does not hold a lock on
 .Fa mutex .
 .El
+.Pp
+.\" -----
+.Fn pthread_mutex_timedlock
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The mutex was created with the protocol attribute having the value
+.Dv PTHREAD_PRIO_PROTECT
+and the calling thread's priority is higher than
+the mutex current priority ceiling.
+.It Bq Er EINVAL
+The process or thread would have blocked, and the
+.Fa timeout
+parameter specified a nanoseconds field value less than zero or greater
+than or equal to 1000 million.
+.It Bq Er ETIMEDOUT
+The mutex could not be locked before the specified timeout expired.
+.El
+.Pp
+.\" -----
+The
+.Fn pthread_mutex_getprioceiling
+and 
+.Fn pthread_mutex_setprioceiling
+functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The priority requested by 
+.Fa prioceiling
+is out of range.
+.It Bq Er EINVAL
+The value specified by 
+.Fa mutex
+does not refer to a currently existing mutex.
+.It Bq Er EPERM
+The caller does not have the privilege to perform the operation.
+
 .\" ----------------------------------------------------------------------------
+
 .Sh SEE ALSO
 .Xr pthread 3 ,
 .Xr pthread_barrier 3 ,

Index: src/lib/libpthread/pthread_mutex.c
diff -u src/lib/libpthread/pthread_mutex.c:1.59 src/lib/libpthread/pthread_mutex.c:1.60
--- src/lib/libpthread/pthread_mutex.c:1.59	Mon Feb  3 10:51:01 2014
+++ src/lib/libpthread/pthread_mutex.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread_mutex.c,v 1.59 2014/02/03 15:51:01 rmind Exp $	*/
+/*	$NetBSD: pthread_mutex.c,v 1.60 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -47,10 +47,11 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_mutex.c,v 1.59 2014/02/03 15:51:01 rmind Exp $");
+__RCSID("$NetBSD: pthread_mutex.c,v 1.60 2016/07/03 14:24:58 christos Exp $");
 
 #include <sys/types.h>
 #include <sys/lwpctl.h>
+#include <sys/sched.h>
 #include <sys/lock.h>
 
 #include <errno.h>
@@ -67,12 +68,27 @@ __RCSID("$NetBSD: pthread_mutex.c,v 1.59
 #define	MUTEX_WAITERS_BIT		((uintptr_t)0x01)
 #define	MUTEX_RECURSIVE_BIT		((uintptr_t)0x02)
 #define	MUTEX_DEFERRED_BIT		((uintptr_t)0x04)
-#define	MUTEX_THREAD			((uintptr_t)-16L)
+#define	MUTEX_PROTECT_BIT		((uintptr_t)0x08)
+#define	MUTEX_THREAD			((uintptr_t)~0x0f)
 
 #define	MUTEX_HAS_WAITERS(x)		((uintptr_t)(x) & MUTEX_WAITERS_BIT)
 #define	MUTEX_RECURSIVE(x)		((uintptr_t)(x) & MUTEX_RECURSIVE_BIT)
+#define	MUTEX_PROTECT(x)		((uintptr_t)(x) & MUTEX_PROTECT_BIT)
 #define	MUTEX_OWNER(x)			((uintptr_t)(x) & MUTEX_THREAD)
 
+#define	MUTEX_GET_TYPE(x)		\
+    ((int)(((uintptr_t)(x) & 0x000000ff) >> 0))
+#define	MUTEX_SET_TYPE(x, t) 		\
+    (x) = (void *)(((uintptr_t)(x) & ~0x000000ff) | ((t) << 0))
+#define	MUTEX_GET_PROTOCOL(x)		\
+    ((int)(((uintptr_t)(x) & 0x0000ff00) >> 8))
+#define	MUTEX_SET_PROTOCOL(x, p)	\
+    (x) = (void *)(((uintptr_t)(x) & ~0x0000ff00) | ((p) << 8))
+#define	MUTEX_GET_CEILING(x)		\
+    ((int)(((uintptr_t)(x) & 0x00ff0000) >> 16))
+#define	MUTEX_SET_CEILING(x, c)	\
+    (x) = (void *)(((uintptr_t)(x) & ~0x00ff0000) | ((c) << 16))
+
 #if __GNUC_PREREQ__(3, 0)
 #define	NOINLINE		__attribute ((noinline))
 #else
@@ -80,7 +96,8 @@ __RCSID("$NetBSD: pthread_mutex.c,v 1.59
 #endif
 
 static void	pthread__mutex_wakeup(pthread_t, pthread_mutex_t *);
-static int	pthread__mutex_lock_slow(pthread_mutex_t *);
+static int	pthread__mutex_lock_slow(pthread_mutex_t *,
+    const struct timespec *);
 static int	pthread__mutex_unlock_slow(pthread_mutex_t *);
 static void	pthread__mutex_pause(void);
 
@@ -103,16 +120,22 @@ __strong_alias(__libc_mutexattr_settype,
 int
 pthread_mutex_init(pthread_mutex_t *ptm, const pthread_mutexattr_t *attr)
 {
-	intptr_t type;
+	uintptr_t type, proto, val, ceil;
 
 	if (__predict_false(__uselibcstub))
 		return __libc_mutex_init_stub(ptm, attr);
 
-	if (attr == NULL)
+	if (attr == NULL) {
 		type = PTHREAD_MUTEX_NORMAL;
-	else
-		type = (intptr_t)attr->ptma_private;
+		proto = PTHREAD_PRIO_NONE;
+		ceil = 0;
+	} else {
+		val = (uintptr_t)attr->ptma_private;
 
+		type = MUTEX_GET_TYPE(val);
+		proto = MUTEX_GET_PROTOCOL(val);
+		ceil = MUTEX_GET_CEILING(val);
+	}
 	switch (type) {
 	case PTHREAD_MUTEX_ERRORCHECK:
 		__cpu_simple_lock_set(&ptm->ptm_errorcheck);
@@ -127,10 +150,18 @@ pthread_mutex_init(pthread_mutex_t *ptm,
 		ptm->ptm_owner = NULL;
 		break;
 	}
+	switch (proto) {
+	case PTHREAD_PRIO_PROTECT:
+		val = (uintptr_t)ptm->ptm_owner;
+		val |= MUTEX_PROTECT_BIT;
+		ptm->ptm_owner = (void *)val;
+		break;
 
+	}
 	ptm->ptm_magic = _PT_MUTEX_MAGIC;
 	ptm->ptm_waiters = NULL;
 	ptm->ptm_recursed = 0;
+	ptm->ptm_ceiling = (unsigned char)ceil;
 
 	return 0;
 }
@@ -168,7 +199,24 @@ pthread_mutex_lock(pthread_mutex_t *ptm)
 #endif
 		return 0;
 	}
-	return pthread__mutex_lock_slow(ptm);
+	return pthread__mutex_lock_slow(ptm, NULL);
+}
+
+int
+pthread_mutex_timedlock(pthread_mutex_t* ptm, const struct timespec *ts)
+{
+	pthread_t self;
+	void *val;
+
+	self = pthread__self();
+	val = atomic_cas_ptr(&ptm->ptm_owner, NULL, self);
+	if (__predict_true(val == NULL)) {
+#ifndef PTHREAD__ATOMIC_IS_MEMBAR
+		membar_enter();
+#endif
+		return 0;
+	}
+	return pthread__mutex_lock_slow(ptm, ts);
 }
 
 /* We want function call overhead. */
@@ -258,11 +306,12 @@ again:
 }
 
 NOINLINE static int
-pthread__mutex_lock_slow(pthread_mutex_t *ptm)
+pthread__mutex_lock_slow(pthread_mutex_t *ptm, const struct timespec *ts)
 {
 	void *waiters, *new, *owner, *next;
 	pthread_t self;
 	int serrno;
+	int error;
 
 	pthread__error(EINVAL, "Invalid mutex",
 	    ptm->ptm_magic == _PT_MUTEX_MAGIC);
@@ -282,6 +331,10 @@ pthread__mutex_lock_slow(pthread_mutex_t
 			return EDEADLK;
 	}
 
+	/* priority protect */
+	if (MUTEX_PROTECT(owner) && _sched_protect(ptm->ptm_ceiling) == -1) {
+		return errno;
+	}
 	serrno = errno;
 	for (;; owner = ptm->ptm_owner) {
 		/* Spin while the owner is running. */
@@ -339,12 +392,23 @@ pthread__mutex_lock_slow(pthread_mutex_t
 		 */
 		while (self->pt_mutexwait) {
 			self->pt_blocking++;
-			(void)_lwp_park(CLOCK_REALTIME, TIMER_ABSTIME, NULL,
+			error = _lwp_park(CLOCK_REALTIME, TIMER_ABSTIME, ts,
 			    self->pt_unpark, __UNVOLATILE(&ptm->ptm_waiters),
 			    __UNVOLATILE(&ptm->ptm_waiters));
 			self->pt_unpark = 0;
 			self->pt_blocking--;
 			membar_sync();
+			if (__predict_true(error != -1)) {
+				continue;
+			}
+			if (errno == ETIMEDOUT && self->pt_mutexwait) {
+				/*Remove self from waiters list*/
+				pthread__mutex_wakeup(self, ptm);
+				/*priority protect*/
+				if (MUTEX_PROTECT(owner))
+					(void)_sched_protect(-1);
+				return ETIMEDOUT;
+			}
 		}
 	}
 }
@@ -460,6 +524,10 @@ pthread__mutex_unlock_slow(pthread_mutex
 	 */
 	if (new != owner) {
 		owner = atomic_swap_ptr(&ptm->ptm_owner, new);
+		if (__predict_false(MUTEX_PROTECT(owner))) {
+			/* restore elevated priority */
+			(void)_sched_protect(-1);
+		}
 		if (MUTEX_HAS_WAITERS(owner) != 0) {
 			pthread__mutex_wakeup(self, ptm);
 			return 0;
@@ -591,16 +659,18 @@ pthread_mutexattr_destroy(pthread_mutexa
 int
 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep)
 {
+
 	pthread__error(EINVAL, "Invalid mutex attribute",
 	    attr->ptma_magic == _PT_MUTEXATTR_MAGIC);
 
-	*typep = (int)(intptr_t)attr->ptma_private;
+	*typep = MUTEX_GET_TYPE(attr->ptma_private);
 	return 0;
 }
 
 int
 pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
 {
+
 	if (__predict_false(__uselibcstub))
 		return __libc_mutexattr_settype_stub(attr, type);
 
@@ -611,13 +681,92 @@ pthread_mutexattr_settype(pthread_mutexa
 	case PTHREAD_MUTEX_NORMAL:
 	case PTHREAD_MUTEX_ERRORCHECK:
 	case PTHREAD_MUTEX_RECURSIVE:
-		attr->ptma_private = (void *)(intptr_t)type;
+		MUTEX_SET_TYPE(attr->ptma_private, type);
+		return 0;
+	default:
+		return EINVAL;
+	}
+}
+
+int
+pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int*proto)
+{
+	
+	pthread__error(EINVAL, "Invalid mutex attribute",
+	    attr->ptma_magic == _PT_MUTEXATTR_MAGIC);
+
+	*proto = MUTEX_GET_PROTOCOL(attr->ptma_private);
+	return 0;
+}
+
+int 
+pthread_mutexattr_setprotocol(pthread_mutexattr_t* attr, int proto)
+{
+
+	pthread__error(EINVAL, "Invalid mutex attribute",
+	    attr->ptma_magic == _PT_MUTEXATTR_MAGIC);
+
+	switch (proto) {
+	case PTHREAD_PRIO_NONE:
+	case PTHREAD_PRIO_PROTECT:
+		MUTEX_SET_PROTOCOL(attr->ptma_private, proto);
 		return 0;
+	case PTHREAD_PRIO_INHERIT:
+		return ENOTSUP;
 	default:
 		return EINVAL;
 	}
 }
 
+int 
+pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceil)
+{
+	
+	pthread__error(EINVAL, "Invalid mutex attribute",
+		attr->ptma_magic == _PT_MUTEXATTR_MAGIC);
+
+	*ceil = MUTEX_GET_CEILING(attr->ptma_private);
+	return 0;
+}
+
+int 
+pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int ceil) 
+{
+
+	pthread__error(EINVAL, "Invalid mutex attribute",
+		attr->ptma_magic == _PT_MUTEXATTR_MAGIC);
+
+	if (ceil & ~0xff)
+		return EINVAL;
+
+	MUTEX_SET_CEILING(attr->ptma_private, ceil);
+	return 0;
+}
+
+#ifdef _PTHREAD_PSHARED
+int
+pthread_mutexattr_getpshared(const pthread_mutexattr_t * __restrict attr,
+    int * __restrict pshared)
+{
+
+	*pshared = PTHREAD_PROCESS_PRIVATE;
+	return 0;
+}
+
+int
+pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
+{
+
+	switch(pshared) {
+	case PTHREAD_PROCESS_PRIVATE:
+		return 0;
+	case PTHREAD_PROCESS_SHARED:
+		return ENOSYS;
+	}
+	return EINVAL;
+}
+#endif
+
 /*
  * pthread__mutex_deferwake: try to defer unparking threads in self->pt_waiters
  *
@@ -645,6 +794,28 @@ pthread__mutex_deferwake(pthread_t self,
 }
 
 int
+pthread_mutex_getprioceiling(const pthread_mutex_t *ptm, int*ceil) 
+{
+	*ceil = (unsigned int)ptm->ptm_ceiling;
+	return 0;
+}
+
+int
+pthread_mutex_setprioceiling(pthread_mutex_t *ptm, int ceil, int *old_ceil) 
+{
+	int error;
+
+	error = pthread_mutex_lock(ptm);
+	if (error == 0) {
+		*old_ceil = (unsigned int)ptm->ptm_ceiling;
+		/*check range*/
+		ptm->ptm_ceiling = (unsigned char)ceil;
+		pthread_mutex_unlock(ptm);
+	}
+	return error;
+}
+
+int
 _pthread_mutex_held_np(pthread_mutex_t *ptm)
 {
 

Index: src/lib/libpthread/pthread_mutexattr.3
diff -u src/lib/libpthread/pthread_mutexattr.3:1.11 src/lib/libpthread/pthread_mutexattr.3:1.12
--- src/lib/libpthread/pthread_mutexattr.3:1.11	Thu Jul  8 18:46:34 2010
+++ src/lib/libpthread/pthread_mutexattr.3	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-.\" $NetBSD: pthread_mutexattr.3,v 1.11 2010/07/08 22:46:34 jruoho Exp $
+.\" $NetBSD: pthread_mutexattr.3,v 1.12 2016/07/03 14:24:58 christos Exp $
 .\"
 .\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -50,18 +50,20 @@
 .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\" $FreeBSD: src/lib/libpthread/man/pthread_mutexattr.3,v 1.8 2002/09/16 19:29:29 mini Exp $
-.Dd July 9, 2010
+.Dd June 12, 2016
 .Dt PTHREAD_MUTEXATTR 3
 .Os
 .Sh NAME
 .Nm pthread_mutexattr_init ,
 .Nm pthread_mutexattr_destroy ,
-.\" .Nm pthread_mutexattr_setprioceiling ,
-.\" .Nm pthread_mutexattr_getprioceiling ,
-.\" .Nm pthread_mutexattr_setprotocol ,
-.\" .Nm pthread_mutexattr_getprotocol ,
+.Nm pthread_mutexattr_setprioceiling ,
+.Nm pthread_mutexattr_getprioceiling ,
+.Nm pthread_mutexattr_setprotocol ,
+.Nm pthread_mutexattr_getprotocol ,
 .Nm pthread_mutexattr_settype ,
-.Nm pthread_mutexattr_gettype
+.Nm pthread_mutexattr_gettype ,
+.Nm pthread_mutexattr_getpshared ,
+.Nm pthread_mutexattr_setpshared
 .Nd mutex attribute operations
 .Sh LIBRARY
 .Lb libpthread
@@ -71,23 +73,29 @@
 .Fn pthread_mutexattr_init "pthread_mutexattr_t *attr"
 .Ft int
 .Fn pthread_mutexattr_destroy "pthread_mutexattr_t *attr"
-.\" .Ft int
-.\" .Fn pthread_mutexattr_setprioceiling \
-.\" "pthread_mutexattr_t *attr" "int prioceiling"
-.\" .Ft int
-.\" .Fn pthread_mutexattr_getprioceiling \
-.\" "pthread_mutexattr_t *attr" "int *prioceiling"
-.\" .Ft int
-.\" .Fn pthread_mutexattr_setprotocol \
-.\" "pthread_mutexattr_t *attr" "int protocol"
-.\" .Ft int
-.\" .Fn pthread_mutexattr_getprotocol \
-.\" "pthread_mutexattr_t *attr" "int *protocol"
+.Ft int
+.Fn pthread_mutexattr_setprioceiling \
+"pthread_mutexattr_t *attr" "int prioceiling"
+.Ft int
+.Fn pthread_mutexattr_getprioceiling \
+"pthread_mutexattr_t *attr" "int *prioceiling"
+.Ft int
+.Fn pthread_mutexattr_setprotocol \
+"pthread_mutexattr_t *attr" "int protocol"
+.Ft int
+.Fn pthread_mutexattr_getprotocol \
+"pthread_mutexattr_t *attr" "int *protocol"
 .Ft int
 .Fn pthread_mutexattr_settype "pthread_mutexattr_t *attr" "int type"
 .Ft int
 .Fn pthread_mutexattr_gettype \
 "pthread_mutexattr_t * restrict attr" "int * restrict type"
+.Ft int
+.Fn pthread_mutexattr_getpshared \
+"const pthread_mutexattr_t * __restrict attr" "int * __restrict pshared"
+.Ft int
+.Fn pthread_mutexattr_setpshared \
+"pthread_mutexattr_t * attr" "int pshared"
 .Sh DESCRIPTION
 Mutex attributes are used to specify parameters to
 .Fn pthread_mutex_init .
@@ -172,6 +180,38 @@ The
 .Fn pthread_mutexattr_gettype
 functions copy the type value of the attribute to the location
 pointed to by the second parameter.
+.Pp
+The
+.Fn pthread_mutexattr_getpshared
+function obtains the value of the process-shared attribute from 
+the attributes object referenced by 
+.Fa attr.
+.Pp
+The 
+.Fn pthread_mutexattr_setpshared
+function is used to set the process-shared attribute in an initialised
+attributes object referenced by
+.Fa attr.
+.Pp
+The 
+.Fn pthread_mutexattr_getprotocol
+and
+.Fn pthread_mutexattr_setprotocol
+functions shall get and set the protocol attribute of a mutex attributes 
+object pointed to by
+.Fa attr 
+which was previously created by the function
+.Fn pthread_mutexattr_init .
+.Pp
+The 
+.Fn pthread_mutexattr_getprioceiling
+and
+.Fn pthread_mutexattr_setprioceiling
+functions, shall get and set the priority ceiling attribute of a mutex attributes
+object pointed to by 
+.Fa attr 
+which was previously created by the function
+.Fn pthread_mutexattr_init .
 .Sh RETURN VALUES
 If successful, these functions return 0.
 Otherwise, an error number is returned to indicate the error.
@@ -201,46 +241,63 @@ No error numbers are defined for the
 and
 .Fn pthread_mutexattr_gettype
 functions.
-.\"
-.\" .Pp
-.\" .Fn pthread_mutexattr_setprioceiling
-.\" may fail if:
-.\" .Bl -tag -width Er
-.\" .It Bq Er EINVAL
-.\" Invalid value for
-.\" .Fa attr ,
-.\" or invalid value for
-.\" .Fa prioceiling .
-.\" .El
-.\" .Pp
-.\" .Fn pthread_mutexattr_getprioceiling
-.\" may fail if:
-.\" .Bl -tag -width Er
-.\" .It Bq Er EINVAL
-.\" Invalid value for
-.\" .Fa attr .
-.\" .El
-.\" .Pp
-.\" .Fn pthread_mutexattr_setprotocol
-.\" may fail if:
-.\" .Bl -tag -width Er
-.\" .It Bq Er EINVAL
-.\" Invalid value for
-.\" .Fa attr ,
-.\" or invalid value for
-.\" .Fa protocol .
-.\" .El
-.\" .Pp
-.\" .Fn pthread_mutexattr_getprotocol
-.\" may fail if:
-.\" .Bl -tag -width Er
-.\" .It Bq Er EINVAL
-.\" Invalid value for
-.\" .Fa attr .
-.\" .El
-.\" .Pp
+.Pp
+.Fn pthread_mutexattr_setprioceiling
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Invalid value for
+.Fa attr ,
+or invalid value for
+.Fa prioceiling .
+.El
+.Pp
+.Fn pthread_mutexattr_getprioceiling
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Invalid value for
+.Fa attr .
+.El
+.Pp
+.Fn pthread_mutexattr_setprotocol
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Invalid value for
+.Fa attr ,
+or invalid value for
+.Fa protocol .
+.El
+.Pp
+.Fn pthread_mutexattr_getprotocol
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Invalid value for
+.Fa attr .
+.El
+.Pp
+.El
+.Pp
+.Fn pthread_mutexattr_getpshared
+and 
+.Fn pthread_mutexattr_setpshared
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+the value specified by 
+.Fa attr
+is invalid.
 .Sh SEE ALSO
 .Xr pthread_mutex_init 3
 .Sh STANDARDS
 These functions conform to
 .St -p1003.1-2001 .
+.Sh BUGS
+The
+.Fn pthread_mutexattr_getpshared
+and
+.Fn pthread_mutexattr_setpshared
+functions are hidden by default since only thread shared attributes
+are supported.

Index: src/lib/libpthread/pthread_rwlock.c
diff -u src/lib/libpthread/pthread_rwlock.c:1.33 src/lib/libpthread/pthread_rwlock.c:1.34
--- src/lib/libpthread/pthread_rwlock.c:1.33	Thu Mar 21 12:49:12 2013
+++ src/lib/libpthread/pthread_rwlock.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread_rwlock.c,v 1.33 2013/03/21 16:49:12 christos Exp $ */
+/*	$NetBSD: pthread_rwlock.c,v 1.34 2016/07/03 14:24:58 christos Exp $ */
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_rwlock.c,v 1.33 2013/03/21 16:49:12 christos Exp $");
+__RCSID("$NetBSD: pthread_rwlock.c,v 1.34 2016/07/03 14:24:58 christos Exp $");
 
 #include <sys/types.h>
 #include <sys/lwpctl.h>
@@ -639,6 +639,29 @@ _pthread_rwlock_wrheld_np(pthread_rwlock
 	    ((uintptr_t)pthread__self() | RW_WRITE_LOCKED);
 }
 
+#ifdef _PTHREAD_PSHARED
+int
+pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * __restrict attr,
+    int * __restrict pshared)
+{
+	*pshared = PTHREAD_PROCESS_PRIVATE;
+	return 0;
+}
+
+int
+pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared)
+{
+
+	switch(pshared) {
+	case PTHREAD_PROCESS_PRIVATE:
+		return 0;
+	case PTHREAD_PROCESS_SHARED:
+		return ENOSYS;
+	}
+	return EINVAL;
+}
+#endif
+
 int
 pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
 {

Index: src/lib/libpthread/pthread_rwlockattr.3
diff -u src/lib/libpthread/pthread_rwlockattr.3:1.8 src/lib/libpthread/pthread_rwlockattr.3:1.9
--- src/lib/libpthread/pthread_rwlockattr.3:1.8	Fri Jul  9 04:51:28 2010
+++ src/lib/libpthread/pthread_rwlockattr.3	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-.\" $NetBSD: pthread_rwlockattr.3,v 1.8 2010/07/09 08:51:28 jruoho Exp $
+.\" $NetBSD: pthread_rwlockattr.3,v 1.9 2016/07/03 14:24:58 christos Exp $
 .\"
 .\" Copyright (c) 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -48,13 +48,15 @@
 .\"
 .\" $FreeBSD: src/lib/libpthread/man/pthread_rwlockattr_init.3,v 1.7 2002/09/16 19:29:29 mini Exp $
 .\"
-.Dd July 9, 2010
+.Dd June 12, 2016
 .Dt PTHREAD_RWLOCKATTR 3
 .Os
 .Sh NAME
 .Nm pthread_rwlockattr_init ,
-.Nm pthread_rwlockattr_destroy
-.Nd initialize or destroy read/write lock attributes
+.Nm pthread_rwlockattr_destroy ,
+.Nm pthread_rwlockattr_getpshared ,
+.Nm pthread_rwlockattr_setpshared
+.Nd initialize, destroy or query read/write lock attributes
 .Sh LIBRARY
 .Lb libpthread
 .Sh SYNOPSIS
@@ -63,6 +65,10 @@
 .Fn pthread_rwlockattr_init "pthread_rwlockattr_t *attr"
 .Ft int
 .Fn pthread_rwlockattr_destroy "pthread_rwlockattr_t *attr"
+.Ft int
+.Fn pthread_rwlockattr_getpshared "const pthread_rwlockattr_t *__restrict attr" "int * __restrict pshared"
+.Ft int
+.Fn pthread_rwlockattr_setpshared "pthread_rwlockattr_t *attr" "int pshared"
 .Sh DESCRIPTION
 The
 .Fn pthread_rwlockattr_init
@@ -73,12 +79,21 @@ The
 function is used to destroy a read/write lock attribute object
 previously created with
 .Fn pthread_rwlockattr_init .
+.Pp
+The
+.Fn pthread_rwlockattr_getpshared
+function shall obtain the value of process-shared attribute from
+the initialized attributes object referenced by
+.Fa attr.
+.Pp
+The
+.Fn pthread_rwlockattr_setpshared
+function shall set the process-shared attribute in an initialized
+attributes object referenced by
+.Fa attr.
 .Sh RETURN VALUES
-If successful, the
-.Fn pthread_rwlockattr_init
-and
-.Fn pthread_rwlockattr_destroy
-functions return zero.
+If successful, 
+all these functions return zero.
 Otherwise an error number will be returned to indicate the error.
 .Sh ERRORS
 .Fn pthread_rwlockattr_init
@@ -98,8 +113,26 @@ The value specified by
 .Fa attr
 is invalid.
 .El
+.Pp
+.Fn pthread_rwlockattr_getpshared
+and
+.Fn pthread_rwlockattr_setpshared
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value specified by
+.Fa attr
+is invalid.
+.El
 .Sh SEE ALSO
 .Xr pthread_rwlock_init 3
 .Sh STANDARDS
 Both functions conform to
 .St -p1003.1-2001 .
+.Sh BUGS
+The
+.Fn pthread_rwlockattr_getpshared
+and
+.Fn pthread_rwlockattr_setpshared
+functions are hidden by default since only thread shared attributes
+are supported.

Index: src/lib/libpthread/pthread_types.h
diff -u src/lib/libpthread/pthread_types.h:1.17 src/lib/libpthread/pthread_types.h:1.18
--- src/lib/libpthread/pthread_types.h:1.17	Thu Aug 27 08:30:50 2015
+++ src/lib/libpthread/pthread_types.h	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread_types.h,v 1.17 2015/08/27 12:30:50 pooka Exp $	*/
+/*	$NetBSD: pthread_types.h,v 1.18 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2008 The NetBSD Foundation, Inc.
@@ -115,7 +115,7 @@ struct	__pthread_mutex_st {
 #ifdef __CPU_SIMPLE_LOCK_PAD
 	uint8_t		ptm_pad1[3];
 #endif
-	__pthread_spin_t ptm_interlock;	/* unused - backwards compat */
+	__pthread_spin_t ptm_ceiling;
 #ifdef __CPU_SIMPLE_LOCK_PAD
 	uint8_t		ptm_pad2[3];
 #endif

Index: src/sys/kern/kern_lwp.c
diff -u src/sys/kern/kern_lwp.c:1.184 src/sys/kern/kern_lwp.c:1.185
--- src/sys/kern/kern_lwp.c:1.184	Mon Apr  4 19:07:06 2016
+++ src/sys/kern/kern_lwp.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_lwp.c,v 1.184 2016/04/04 23:07:06 christos Exp $	*/
+/*	$NetBSD: kern_lwp.c,v 1.185 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -211,7 +211,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.184 2016/04/04 23:07:06 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.185 2016/07/03 14:24:58 christos Exp $");
 
 #include "opt_ddb.h"
 #include "opt_lockdebug.h"
@@ -829,6 +829,8 @@ lwp_create(lwp_t *l1, proc_t *p2, vaddr_
 	l2->l_kpribase = PRI_KERNEL;
 	l2->l_priority = l1->l_priority;
 	l2->l_inheritedprio = -1;
+	l2->l_protectprio = -1;
+	l2->l_auxprio = -1;
 	l2->l_flag = 0;
 	l2->l_pflag = LP_MPSAFE;
 	TAILQ_INIT(&l2->l_ld_locks);

Index: src/sys/kern/kern_sleepq.c
diff -u src/sys/kern/kern_sleepq.c:1.50 src/sys/kern/kern_sleepq.c:1.51
--- src/sys/kern/kern_sleepq.c:1.50	Fri Sep  5 01:57:21 2014
+++ src/sys/kern/kern_sleepq.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sleepq.c,v 1.50 2014/09/05 05:57:21 matt Exp $	*/
+/*	$NetBSD: kern_sleepq.c,v 1.51 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.50 2014/09/05 05:57:21 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.51 2016/07/03 14:24:58 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -479,5 +479,6 @@ sleepq_lendpri(lwp_t *l, pri_t pri)
 	KASSERT(lwp_locked(l, NULL));
 
 	l->l_inheritedprio = pri;
+	l->l_auxprio = MAX(l->l_inheritedprio, l->l_protectprio);
 	sleepq_reinsert(sq, l);
 }

Index: src/sys/kern/kern_synch.c
diff -u src/sys/kern/kern_synch.c:1.310 src/sys/kern/kern_synch.c:1.311
--- src/sys/kern/kern_synch.c:1.310	Mon Apr  4 16:47:57 2016
+++ src/sys/kern/kern_synch.c	Sun Jul  3 10:24:58 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_synch.c,v 1.310 2016/04/04 20:47:57 christos Exp $	*/
+/*	$NetBSD: kern_synch.c,v 1.311 2016/07/03 14:24:58 christos Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2004, 2006, 2007, 2008, 2009
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.310 2016/04/04 20:47:57 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.311 2016/07/03 14:24:58 christos Exp $");
 
 #include "opt_kstack.h"
 #include "opt_perfctrs.h"
@@ -1085,9 +1085,11 @@ sched_lendpri(struct lwp *l, pri_t pri)
 		KASSERT(lwp_locked(l, l->l_cpu->ci_schedstate.spc_mutex));
 		sched_dequeue(l);
 		l->l_inheritedprio = pri;
+		l->l_auxprio = MAX(l->l_inheritedprio, l->l_protectprio);
 		sched_enqueue(l, false);
 	} else {
 		l->l_inheritedprio = pri;
+		l->l_auxprio = MAX(l->l_inheritedprio, l->l_protectprio);
 	}
 	resched_cpu(l);
 }

Index: src/sys/kern/sys_sched.c
diff -u src/sys/kern/sys_sched.c:1.43 src/sys/kern/sys_sched.c:1.44
--- src/sys/kern/sys_sched.c:1.43	Tue Feb 25 13:30:11 2014
+++ src/sys/kern/sys_sched.c	Sun Jul  3 10:24:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_sched.c,v 1.43 2014/02/25 18:30:11 pooka Exp $	*/
+/*	$NetBSD: sys_sched.c,v 1.44 2016/07/03 14:24:59 christos Exp $	*/
 
 /*
  * Copyright (c) 2008, 2011 Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_sched.c,v 1.43 2014/02/25 18:30:11 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_sched.c,v 1.44 2016/07/03 14:24:59 christos Exp $");
 
 #include <sys/param.h>
 
@@ -532,6 +532,68 @@ out:
 }
 
 /*
+ * Priority protection for PTHREAD_PRIO_PROTECT. This is a weak
+ * analogue of priority inheritance: temp raise the priority
+ * of the caller when accessing a protected resource.
+ */
+int 
+sys__sched_protect(struct lwp *l, 
+    const struct sys__sched_protect_args *uap, register_t *retval)
+{
+        /* {
+                syscallarg(int) priority;
+		syscallarg(int *) opriority;
+        } */
+	int error;
+	pri_t pri;
+
+	KASSERT(l->l_inheritedprio == -1);
+	KASSERT(l->l_auxprio == -1 || l->l_auxprio == l->l_protectprio);
+	
+	pri = SCARG(uap, priority);
+	error = 0;
+	lwp_lock(l);
+	if (pri == -1) {
+		/* back out priority changes */
+		switch(l->l_protectdepth) {
+		case 0:
+			error = EINVAL;
+			break;
+		case 1:
+			l->l_protectdepth = 0;
+			l->l_protectprio = -1;
+			l->l_auxprio = -1;
+			break;
+		default:
+			l->l_protectdepth--;
+			break;	
+		}
+	} else if (pri < 0) {
+		/* Just retrieve the current value, for debugging */
+		if (l->l_protectprio != -1)
+			error = ENOENT;
+		else
+			*retval = l->l_protectprio - PRI_USER_RT;
+	} else if (__predict_false(pri < SCHED_PRI_MIN ||
+	    pri > SCHED_PRI_MAX || l->l_priority > pri + PRI_USER_RT)) {
+		/* must fail if existing priority is higher */
+		error = EPERM;
+	} else {
+		/* play along but make no changes if not a realtime LWP. */
+		l->l_protectdepth++;
+		pri += PRI_USER_RT;
+		if (__predict_true(l->l_class != SCHED_OTHER && 
+		    pri > l->l_protectprio)) {
+			l->l_protectprio = pri;
+			l->l_auxprio = pri;
+		}
+	}
+	lwp_unlock(l);
+
+	return error;
+}
+
+/*
  * Yield.
  */
 int

Index: src/sys/kern/syscalls.master
diff -u src/sys/kern/syscalls.master:1.284 src/sys/kern/syscalls.master:1.285
--- src/sys/kern/syscalls.master:1.284	Sat Apr 23 19:08:26 2016
+++ src/sys/kern/syscalls.master	Sun Jul  3 10:24:59 2016
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.284 2016/04/23 23:08:26 christos Exp $
+	$NetBSD: syscalls.master,v 1.285 2016/07/03 14:24:59 christos Exp $
 
 ;	@(#)syscalls.master	8.2 (Berkeley) 1/13/94
 
@@ -692,7 +692,7 @@
 349	STD 		{ int|sys||_sched_getaffinity(pid_t pid, lwpid_t lid, \
 			    size_t size, cpuset_t *cpuset); }
 350	STD 		{ int|sys||sched_yield(void); }
-351	UNIMPL
+351	STD		{ int|sys||_sched_protect(int priority); }	
 352	UNIMPL
 353	UNIMPL
 

Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.171 src/sys/sys/lwp.h:1.172
--- src/sys/sys/lwp.h:1.171	Wed Jun 15 22:34:33 2016
+++ src/sys/sys/lwp.h	Sun Jul  3 10:24:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: lwp.h,v 1.171 2016/06/16 02:34:33 ozaki-r Exp $	*/
+/*	$NetBSD: lwp.h,v 1.172 2016/07/03 14:24:59 christos Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
@@ -105,6 +105,9 @@ struct lwp {
 	pri_t		l_kpribase;	/* !: kernel priority base level */
 	pri_t		l_priority;	/* l: scheduler priority */
 	pri_t		l_inheritedprio;/* l: inherited priority */
+	pri_t		l_protectprio;	/* l: for PTHREAD_PRIO_PROTECT */
+	pri_t		l_auxprio;	/* l: max(inherit,protect) priority */
+	int		l_protectdepth;	/* l: for PTHREAD_PRIO_PROTECT */
 	SLIST_HEAD(, turnstile) l_pi_lenders; /* l: ts lending us priority */
 	uint64_t	l_ncsw;		/* l: total context switches */
 	uint64_t	l_nivcsw;	/* l: involuntary context switches */
@@ -403,9 +406,6 @@ lwp_lendpri(lwp_t *l, pri_t pri)
 {
 	KASSERT(mutex_owned(l->l_mutex));
 
-	if (l->l_inheritedprio == pri)
-		return;
-
 	(*l->l_syncobj->sobj_lendpri)(l, pri);
 	KASSERT(l->l_inheritedprio == pri);
 }
@@ -418,7 +418,7 @@ lwp_eprio(lwp_t *l)
 	pri = l->l_priority;
 	if ((l->l_flag & LW_SYSTEM) == 0 && l->l_kpriority && pri < PRI_KERNEL)
 		pri = (pri >> 1) + l->l_kpribase;
-	return MAX(l->l_inheritedprio, pri);
+	return MAX(l->l_auxprio, pri);
 }
 
 int lwp_create(lwp_t *, struct proc *, vaddr_t, int,

Index: src/sys/sys/sched.h
diff -u src/sys/sys/sched.h:1.75 src/sys/sys/sched.h:1.76
--- src/sys/sys/sched.h:1.75	Sun Nov 20 23:36:05 2011
+++ src/sys/sys/sched.h	Sun Jul  3 10:24:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: sched.h,v 1.75 2011/11/21 04:36:05 christos Exp $	*/
+/*	$NetBSD: sched.h,v 1.76 2016/07/03 14:24:59 christos Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -124,6 +124,7 @@ int	_sched_getaffinity(pid_t, lwpid_t, s
 int	_sched_setaffinity(pid_t, lwpid_t, size_t, const cpuset_t *);
 int	_sched_getparam(pid_t, lwpid_t, int *, struct sched_param *);
 int	_sched_setparam(pid_t, lwpid_t, int, const struct sched_param *);
+int	_sched_protect(int);
 __END_DECLS
 
 /*

Index: src/sys/sys/unistd.h
diff -u src/sys/sys/unistd.h:1.58 src/sys/sys/unistd.h:1.59
--- src/sys/sys/unistd.h:1.58	Fri Jun 10 19:29:20 2016
+++ src/sys/sys/unistd.h	Sun Jul  3 10:24:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: unistd.h,v 1.58 2016/06/10 23:29:20 christos Exp $	*/
+/*	$NetBSD: unistd.h,v 1.59 2016/07/03 14:24:59 christos Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -146,6 +146,8 @@
 					/* pthread_attr for stack address */
 #define	_POSIX_THREAD_ATTR_STACKADDR	200112L
 					/* _r functions */
+#define	_POSIX_THREAD_PRIO_PROTECT	200112L
+					/* PTHREAD_PRIO_PROTECT */
 #define	_POSIX_THREAD_SAFE_FUNCTIONS	200112L
 					/* timeouts */
 #undef	_POSIX_TIMEOUTS

Index: src/tests/lib/libpthread/t_cond.c
diff -u src/tests/lib/libpthread/t_cond.c:1.6 src/tests/lib/libpthread/t_cond.c:1.7
--- src/tests/lib/libpthread/t_cond.c:1.6	Wed Sep  3 12:23:24 2014
+++ src/tests/lib/libpthread/t_cond.c	Sun Jul  3 10:24:59 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $ */
+/* $NetBSD: t_cond.c,v 1.7 2016/07/03 14:24:59 christos Exp $ */
 
 /*
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
 #include <sys/cdefs.h>
 __COPYRIGHT("@(#) Copyright (c) 2008\
  The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $");
+__RCSID("$NetBSD: t_cond.c,v 1.7 2016/07/03 14:24:59 christos Exp $");
 
 #include <sys/time.h>
 
@@ -547,6 +547,26 @@ ATF_TC_BODY(destroy_after_cancel, tc)
 	PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex));
 }
 
+ATF_TC(condattr);
+ATF_TC_HEAD(condattr, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Checks Condattr");
+}
+ATF_TC_BODY(condattr, tc)
+{
+	pthread_condattr_t condattr;
+	clockid_t clockid;
+
+	PTHREAD_REQUIRE(pthread_condattr_init(&condattr));
+	PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_REALTIME));
+	PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid));
+	ATF_REQUIRE_EQ(clockid, CLOCK_REALTIME);
+	
+	PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC));
+	PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid));	
+ 	ATF_REQUIRE_EQ(clockid, CLOCK_MONOTONIC);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 
@@ -558,6 +578,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, broadcast);
 	ATF_TP_ADD_TC(tp, bogus_timedwaits);
 	ATF_TP_ADD_TC(tp, destroy_after_cancel);
+	ATF_TP_ADD_TC(tp, condattr);
 
 	return atf_no_error();
 }

Index: src/tests/lib/libpthread/t_mutex.c
diff -u src/tests/lib/libpthread/t_mutex.c:1.7 src/tests/lib/libpthread/t_mutex.c:1.8
--- src/tests/lib/libpthread/t_mutex.c:1.7	Mon Nov  3 19:20:19 2014
+++ src/tests/lib/libpthread/t_mutex.c	Sun Jul  3 10:24:59 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: t_mutex.c,v 1.7 2014/11/04 00:20:19 justin Exp $ */
+/* $NetBSD: t_mutex.c,v 1.8 2016/07/03 14:24:59 christos Exp $ */
 
 /*
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -29,12 +29,15 @@
 #include <sys/cdefs.h>
 __COPYRIGHT("@(#) Copyright (c) 2008\
  The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_mutex.c,v 1.7 2014/11/04 00:20:19 justin Exp $");
+__RCSID("$NetBSD: t_mutex.c,v 1.8 2016/07/03 14:24:59 christos Exp $");
 
 #include <pthread.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 #include <unistd.h>
+#include <sys/sched.h>
+#include <sys/param.h>
 
 #include <atf-c.h>
 
@@ -304,12 +307,255 @@ ATF_TC_BODY(mutex4, tc)
 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
 }
 
+static pthread_mutexattr_t attr5;
+static pthread_mutex_t mutex5;
+static int min_fifo_prio, max_fifo_prio;
+
+static void *
+child_func(void* arg)
+{
+	int res;
+
+	printf("child is waiting\n");
+	res = _sched_protect(-2);
+	ATF_REQUIRE_EQ(res, -1);
+	ATF_REQUIRE_EQ(errno, ENOENT);
+	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex5));
+	printf("child is owning resource\n");
+	res = _sched_protect(-2);
+	ATF_REQUIRE_EQ(res,  max_fifo_prio);
+	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
+	printf("child is done\n");
+	
+	return 0;
+}
+
+ATF_TC(mutex5);
+ATF_TC_HEAD(mutex5, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Checks mutexes for priority setting");
+}
+
+ATF_TC_BODY(mutex5, tc)
+{
+	int res;
+	struct sched_param param;
+	pthread_t child;
+
+	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
+	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
+	printf("min prio for FIFO = %d\n", min_fifo_prio);
+	param.sched_priority = min_fifo_prio;
+	/* = 0 OTHER, 1 FIFO, 2 RR, -1 NONE */
+	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
+	printf("previous policy used = %d\n", res);
+
+	res = sched_getscheduler(getpid());
+	ATF_REQUIRE_EQ(res, 1);
+
+	PTHREAD_REQUIRE(pthread_mutexattr_init(&attr5));
+	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&attr5,
+	    PTHREAD_PRIO_PROTECT));
+	PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&attr5,
+	    max_fifo_prio));
+	
+	PTHREAD_REQUIRE(pthread_mutex_init(&mutex5, &attr5));
+	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex5));
+	printf("enter critical section for main\n");
+	PTHREAD_REQUIRE(pthread_create(&child, NULL, child_func, NULL));
+	printf("main starts to sleep\n");
+	sleep(10);
+	printf("main completes\n");
+	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
+	PTHREAD_REQUIRE(pthread_join(child, NULL));
+}
+
+static pthread_mutex_t mutex6;
+static int start = 0;
+static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000;
+
+static void *
+high_prio(void* arg)
+{
+	struct sched_param param;
+	int policy;
+	param.sched_priority = min_fifo_prio + 10;
+	pthread_t childid = pthread_self();
+
+	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
+	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
+	printf("high protect = %d, prio = %d\n",
+	    _sched_protect(-2), param.sched_priority);
+	ATF_REQUIRE_EQ(policy, 1);
+	printf("high prio = %d\n", param.sched_priority);
+	sleep(1);
+	int i;
+	long tmp = 0;
+	for (i = 0; i<20; i++) {
+		while (high_cnt < MAX_LOOP) {
+			tmp += (123456789 % 1234) * (987654321 % 54321);
+			high_cnt += 1;
+		}
+		high_cnt = 0;
+		sleep(1);
+	}
+	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex6));
+	if (start == 0) start = 2;
+	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
+
+	return 0;
+}
+
+static void *
+low_prio(void* arg)
+{
+	struct sched_param param;
+	int policy;
+	param.sched_priority = min_fifo_prio;
+	pthread_t childid = pthread_self();
+	int res = _sched_protect(max_fifo_prio);
+	ATF_REQUIRE_EQ(res, 0);
+	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
+	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
+	printf("low protect = %d, prio = %d\n", _sched_protect(-2),
+	    param.sched_priority);
+	ATF_REQUIRE_EQ(policy, 1);
+	printf("low prio = %d\n", param.sched_priority);
+	sleep(1);
+	for (int i = 0; i < 20; i++) {
+		while (low_cnt < MAX_LOOP) {
+			long tmp;
+			tmp += (123456789 % 1234) * (987654321 % 54321);
+			low_cnt += 1;
+		}
+		low_cnt = 0;
+		sleep(1);
+	}
+	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex6));
+	if (start == 0)
+		start = 1;
+	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
+
+	return 0;
+}
+
+ATF_TC(mutex6);
+ATF_TC_HEAD(mutex6, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Checks scheduling for priority ceiling");
+}
+
+/*
+ * 1. main thread sets itself to be a realtime task and launched two tasks,
+ *    one has higher priority and the other has lower priority.
+ * 2. each child thread(low and high priority thread) sets its scheduler and
+ *    priority.
+ * 3. each child thread did several rounds of computation, after each round it
+ *    sleep 1 second.
+ * 4. the child thread with low priority will call _sched_protect to increase
+ *    its protect priority.
+ * 5. We verify the thread with low priority runs first.
+ *
+ * Why does it work? From the main thread, we launched the high
+ * priority thread first. This gives this thread the benefit of
+ * starting first. The low priority thread did not call _sched_protect(2).
+ * The high priority thread should finish the task first. After each
+ * round of computation, we call sleep, to put the task into the
+ * sleep queue, and wake up again after the timer expires. This
+ * gives the scheduler the chance to decide which task to run. So,
+ * the thread with real high priority will always block the thread
+ * with real low priority.
+ * 
+ */
+ATF_TC_BODY(mutex6, tc)
+{
+	int res;
+	pthread_t high, low;
+	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
+	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
+	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
+	printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio,
+	    max_fifo_prio);
+	struct sched_param param;
+	param.sched_priority = min_fifo_prio;
+	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
+	printf("previous policy used = %d\n", res);
+
+	res = sched_getscheduler(getpid());
+	ATF_REQUIRE_EQ(res, 1);
+	PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL));
+	PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL));
+	sleep(5);
+	PTHREAD_REQUIRE(pthread_join(low, NULL));
+	PTHREAD_REQUIRE(pthread_join(high, NULL));
+	
+	ATF_REQUIRE_EQ(start, 1);
+}
+
+ATF_TC(mutexattr1);
+ATF_TC_HEAD(mutexattr1, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
+}
+
+ATF_TC_BODY(mutexattr1, tc)
+{
+	pthread_mutexattr_t mattr;
+	int protocol, target;
+	
+	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
+
+	target = PTHREAD_PRIO_NONE;
+	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
+	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
+	ATF_REQUIRE_EQ(protocol, target);
+
+	/*
+	target = PTHREAD_PRIO_INHERIT;
+	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
+	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
+	ATF_REQUIRE_EQ(protocol, target);
+	*/
+
+	target = PTHREAD_PRIO_PROTECT;
+	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
+	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
+	ATF_REQUIRE_EQ(protocol, target);
+}
+
+ATF_TC(mutexattr2);
+ATF_TC_HEAD(mutexattr2, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
+}
+
+ATF_TC_BODY(mutexattr2, tc)
+{
+	pthread_mutexattr_t mattr;
+
+	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
+	int max_prio = sched_get_priority_max(SCHED_FIFO);
+	int min_prio = sched_get_priority_min(SCHED_FIFO);
+	for (int i = min_prio; i <= max_prio; i++) {
+		int prioceiling;
+		PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&mattr, i));
+		PTHREAD_REQUIRE(pthread_mutexattr_getprioceiling(&mattr,
+		    &prioceiling));
+		ATF_REQUIRE_EQ(i, prioceiling);
+	}
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, mutex1);
 	ATF_TP_ADD_TC(tp, mutex2);
 	ATF_TP_ADD_TC(tp, mutex3);
 	ATF_TP_ADD_TC(tp, mutex4);
-
+	ATF_TP_ADD_TC(tp, mutex5);
+	ATF_TP_ADD_TC(tp, mutex6);
+	ATF_TP_ADD_TC(tp, mutexattr1);
+	ATF_TP_ADD_TC(tp, mutexattr2);
+	
 	return atf_no_error();
 }

Reply via email to