[rtems-libbsd commit] Replace RTEMS objects with custom implementation

Sebastian Huber sebh at rtems.org
Tue Sep 23 08:42:00 UTC 2014


Module:    rtems-libbsd
Branch:    master
Commit:    be43b79fcabb7551677e2d27c75e2a500e2ba622
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=be43b79fcabb7551677e2d27c75e2a500e2ba622

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Sep 22 13:42:26 2014 +0200

Replace RTEMS objects with custom implementation

Performance analysis revealed that the standard RTEMS objects are a
major bottleneck.  The object get mechanism and attribute checks at
runtime have a significant overhead.  Use a custom implementation for
synchronization primitives.  This drops also the size of the
synchronization primitives considerably.

---

 Makefile                                       |   24 ++
 freebsd-to-rtems.py                            |    2 +
 freebsd/sys/sys/_lock.h                        |   10 +-
 freebsd/sys/sys/_mutex.h                       |    5 +
 freebsd/sys/sys/_rwlock.h                      |    7 +
 freebsd/sys/sys/_sx.h                          |    5 +
 freebsd/sys/sys/condvar.h                      |   11 +-
 rtemsbsd/include/machine/rtems-bsd-mutex.h     |   60 +++
 rtemsbsd/include/machine/rtems-bsd-muteximpl.h |  220 ++++++++++
 rtemsbsd/include/machine/rtems-bsd-support.h   |   14 -
 rtemsbsd/rtems/rtems-bsd-condvar.c             |  120 +++----
 rtemsbsd/rtems/rtems-bsd-mutex.c               |  108 +-----
 rtemsbsd/rtems/rtems-bsd-rwlock.c              |   68 +---
 rtemsbsd/rtems/rtems-bsd-shell.c               |   69 +---
 rtemsbsd/rtems/rtems-bsd-sx.c                  |  102 +----
 testsuite/condvar01/test_main.c                |  396 ++++++++++++++++++
 testsuite/mutex01/test_main.c                  |  520 ++++++++++++++++++++++++
 testsuite/rwlock01/test_main.c                 |    6 -
 18 files changed, 1334 insertions(+), 413 deletions(-)

diff --git a/Makefile b/Makefile
index 9a11ef1..d3c663c 100644
--- a/Makefile
+++ b/Makefile
@@ -1316,6 +1316,30 @@ TESTS += $(TEST_THREAD01)
 O_FILES += $(TEST_THREAD01_O_FILES)
 D_FILES += $(TEST_THREAD01_D_FILES)
 RUN_TESTS += $(TEST_THREAD01)
+
+TEST_MUTEX01 = testsuite/mutex01/mutex01.exe
+TEST_MUTEX01_O_FILES =
+TEST_MUTEX01_D_FILES =
+TEST_MUTEX01_O_FILES += testsuite/mutex01/test_main.o
+TEST_MUTEX01_D_FILES += testsuite/mutex01/test_main.d
+$(TEST_MUTEX01): $(TEST_MUTEX01_O_FILES) $(LIB)
+	$(LINK.c) -Wl,-Map,testsuite/mutex01/mutex01.map $^ -lm -lz -o $@
+TESTS += $(TEST_MUTEX01)
+O_FILES += $(TEST_MUTEX01_O_FILES)
+D_FILES += $(TEST_MUTEX01_D_FILES)
+RUN_TESTS += $(TEST_MUTEX01)
+
+TEST_CONDVAR01 = testsuite/condvar01/condvar01.exe
+TEST_CONDVAR01_O_FILES =
+TEST_CONDVAR01_D_FILES =
+TEST_CONDVAR01_O_FILES += testsuite/condvar01/test_main.o
+TEST_CONDVAR01_D_FILES += testsuite/condvar01/test_main.d
+$(TEST_CONDVAR01): $(TEST_CONDVAR01_O_FILES) $(LIB)
+	$(LINK.c) -Wl,-Map,testsuite/condvar01/condvar01.map $^ -lm -lz -o $@
+TESTS += $(TEST_CONDVAR01)
+O_FILES += $(TEST_CONDVAR01_O_FILES)
+D_FILES += $(TEST_CONDVAR01_D_FILES)
+RUN_TESTS += $(TEST_CONDVAR01)
 LIB_C_FILES += dhcpcd/arp.c
 dhcpcd/arp.o: dhcpcd/arp.c
 	$(CC) $(CPPFLAGS) $(CFLAGS) -D__FreeBSD__ -DTHERE_IS_NO_FORK -DMASTER_ONLY -DINET -DINET6 -c $< -o $@
diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py
index 695a3d2..947beba 100755
--- a/freebsd-to-rtems.py
+++ b/freebsd-to-rtems.py
@@ -2473,6 +2473,8 @@ tests.addTest('swi01', ['init', 'swi_test'])
 tests.addTest('timeout01', ['init', 'timeout_test'])
 tests.addTest('init01', ['test_main'])
 tests.addTest('thread01', ['test_main'])
+tests.addTest('mutex01', ['test_main'])
+tests.addTest('condvar01', ['test_main'])
 
 dhcpcd = Module('dhcpcd')
 dhcpcd.addSourceFiles(
diff --git a/freebsd/sys/sys/_lock.h b/freebsd/sys/sys/_lock.h
index 457ffd4..35decd7 100644
--- a/freebsd/sys/sys/_lock.h
+++ b/freebsd/sys/sys/_lock.h
@@ -31,19 +31,11 @@
 #ifndef _SYS__LOCK_H_
 #define	_SYS__LOCK_H_
 
-#ifdef __rtems__
-#include <rtems.h>
-#include <rtems/chain.h>
-#endif
 struct lock_object {
-#ifdef __rtems__
-	rtems_chain_node lo_node;
-	rtems_id lo_id;
-#endif /* __rtems__ */
 	const	char *lo_name;		/* Individual lock name. */
 	u_int	lo_flags;
-	u_int	lo_data;		/* General class specific data. */
 #ifndef __rtems__
+	u_int	lo_data;		/* General class specific data. */
 	struct	witness *lo_witness;	/* Data for witness. */
 #endif /* __rtems__ */
 };
diff --git a/freebsd/sys/sys/_mutex.h b/freebsd/sys/sys/_mutex.h
index 9bf2d39..2f4a674 100644
--- a/freebsd/sys/sys/_mutex.h
+++ b/freebsd/sys/sys/_mutex.h
@@ -30,6 +30,9 @@
 
 #ifndef _SYS__MUTEX_H_
 #define	_SYS__MUTEX_H_
+#ifdef __rtems__
+#include <machine/rtems-bsd-mutex.h>
+#endif /* __rtems__ */
 
 /*
  * Sleep/spin mutex.
@@ -38,6 +41,8 @@ struct mtx {
 	struct lock_object	lock_object;	/* Common lock properties. */
 #ifndef __rtems__
 	volatile uintptr_t	mtx_lock;	/* Owner and flags. */
+#else /* __rtems__ */
+	rtems_bsd_mutex mutex;
 #endif /* __rtems__ */
 };
 
diff --git a/freebsd/sys/sys/_rwlock.h b/freebsd/sys/sys/_rwlock.h
index c5adac0..25eb55e 100644
--- a/freebsd/sys/sys/_rwlock.h
+++ b/freebsd/sys/sys/_rwlock.h
@@ -31,13 +31,20 @@
 
 #ifndef _SYS__RWLOCK_H_
 #define	_SYS__RWLOCK_H_
+#ifdef __rtems__
+#include <machine/rtems-bsd-mutex.h>
+#endif /* __rtems__ */
 
 /*
  * Reader/writer lock.
  */
 struct rwlock {
 	struct lock_object	lock_object;
+#ifndef __rtems__
 	volatile uintptr_t	rw_lock;
+#else /* __rtems__ */
+	rtems_bsd_mutex mutex;
+#endif /* __rtems__ */
 };
 
 #endif /* !_SYS__RWLOCK_H_ */
diff --git a/freebsd/sys/sys/_sx.h b/freebsd/sys/sys/_sx.h
index 699316b..b07ac47 100644
--- a/freebsd/sys/sys/_sx.h
+++ b/freebsd/sys/sys/_sx.h
@@ -30,6 +30,9 @@
 
 #ifndef	_SYS__SX_H_
 #define	_SYS__SX_H_
+#ifdef __rtems__
+#include <machine/rtems-bsd-mutex.h>
+#endif /* __rtems__ */
 
 /*
  * Shared/exclusive lock main structure definition.
@@ -38,6 +41,8 @@ struct sx {
 	struct lock_object	lock_object;
 #ifndef __rtems__
 	volatile uintptr_t	sx_lock;
+#else /* __rtems__ */
+	rtems_bsd_mutex mutex;
 #endif /* __rtems__ */
 };
 
diff --git a/freebsd/sys/sys/condvar.h b/freebsd/sys/sys/condvar.h
index 51da817..8b2ee4d 100644
--- a/freebsd/sys/sys/condvar.h
+++ b/freebsd/sys/sys/condvar.h
@@ -44,17 +44,14 @@ TAILQ_HEAD(cv_waitq, thread);
  * optimization to avoid looking up the sleep queue if there are no waiters.
  */
 #ifdef __rtems__
-#include <pthread.h>
-#include <rtems/chain.h>
-#endif
-struct cv {
-#ifdef __rtems__
-	rtems_chain_node cv_node;
-	pthread_cond_t cv_id;
+#include <rtems/score/threadq.h>
 #endif /* __rtems__ */
+struct cv {
 	const char	*cv_description;
 #ifndef __rtems__
 	int		cv_waiters;
+#else /* __rtems__ */
+  Thread_queue_Control cv_waiters;
 #endif /* __rtems__ */
 };
 
diff --git a/rtemsbsd/include/machine/rtems-bsd-mutex.h b/rtemsbsd/include/machine/rtems-bsd-mutex.h
new file mode 100644
index 0000000..58b16f2
--- /dev/null
+++ b/rtemsbsd/include/machine/rtems-bsd-mutex.h
@@ -0,0 +1,60 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bsd_machine
+ *
+ * @brief TODO.
+ */
+
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEX_H_
+#define _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEX_H_
+
+#include <rtems/score/rbtree.h>
+#include <rtems/score/thread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct {
+	Thread_Control *owner;
+	int nest_level;
+	RBTree_Control rivals;
+} rtems_bsd_mutex;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEX_H_ */
diff --git a/rtemsbsd/include/machine/rtems-bsd-muteximpl.h b/rtemsbsd/include/machine/rtems-bsd-muteximpl.h
new file mode 100644
index 0000000..69b42eb
--- /dev/null
+++ b/rtemsbsd/include/machine/rtems-bsd-muteximpl.h
@@ -0,0 +1,220 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bsd_machine
+ *
+ * @brief Implementation of a mutex with a simple priority inheritance
+ * protocol.
+ */
+
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_
+#define _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_
+
+#include <machine/rtems-bsd-mutex.h>
+#include <machine/rtems-bsd-support.h>
+
+#include <rtems/bsd/sys/types.h>
+#include <rtems/bsd/sys/lock.h>
+
+#include <rtems/score/isr.h>
+#include <rtems/score/rbtreeimpl.h>
+#include <rtems/score/schedulerimpl.h>
+#include <rtems/score/threaddispatch.h>
+#include <rtems/score/threadimpl.h>
+#include <rtems/score/threadqimpl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+static inline void
+rtems_bsd_mutex_init(struct lock_object *lock, rtems_bsd_mutex *m,
+    struct lock_class *class, const char *name, const char *type, int flags)
+{
+	m->owner = NULL;
+	m->nest_level = 0;
+	_RBTree_Initialize_empty(&m->rivals);
+
+	lock_init(lock, class, name, type, flags);
+}
+
+static inline void
+rtems_bsd_mutex_lock(struct lock_object *lock, rtems_bsd_mutex *m)
+{
+	ISR_Level level;
+	Thread_Control *executing;
+	Thread_Control *owner;
+
+	_ISR_Disable(level);
+
+	owner = m->owner;
+	executing = _Thread_Executing;
+
+	if (owner == NULL) {
+		m->owner = executing;
+		++executing->resource_count;
+
+		_ISR_Enable(level);
+	} else if (owner == executing) {
+		BSD_ASSERT(lock->lo_flags & LO_RECURSABLE);
+		++m->nest_level;
+
+		_ISR_Enable(level);
+	} else {
+		_RBTree_Insert(&m->rivals, &executing->RBNode,
+		    _Thread_queue_Compare_priority, false);
+		++executing->resource_count;
+
+		_Thread_Disable_dispatch();
+		_ISR_Enable(level);
+
+		_Scheduler_Change_priority_if_higher(_Scheduler_Get(owner),
+		    owner, executing->current_priority, false);
+		_Thread_Set_state(executing, STATES_WAITING_FOR_MUTEX);
+
+		_Thread_Enable_dispatch();
+	}
+}
+
+static inline int
+rtems_bsd_mutex_trylock(struct lock_object *lock, rtems_bsd_mutex *m)
+{
+	int success;
+	ISR_Level level;
+	Thread_Control *executing;
+	Thread_Control *owner;
+
+	_ISR_Disable(level);
+
+	owner = m->owner;
+	executing = _Thread_Executing;
+
+	if (owner == NULL) {
+		m->owner = executing;
+		++executing->resource_count;
+		success = 1;
+	} else if (owner == executing) {
+		BSD_ASSERT(lock->lo_flags & LO_RECURSABLE);
+		++m->nest_level;
+		success = 1;
+	} else {
+		success = 0;
+	}
+
+	_ISR_Enable(level);
+
+	return (success);
+}
+
+static inline void
+rtems_bsd_mutex_unlock(rtems_bsd_mutex *m)
+{
+	ISR_Level level;
+	int nest_level;
+
+	_ISR_Disable(level);
+
+	nest_level = m->nest_level;
+	if (nest_level != 0) {
+		m->nest_level = nest_level - 1;
+
+		_ISR_Enable(level);
+	} else {
+		RBTree_Node *first;
+		Thread_Control *owner = m->owner;
+
+		BSD_ASSERT(owner == _Thread_Executing);
+		--owner->resource_count;
+
+		first = _RBTree_Get(&m->rivals, RBT_LEFT);
+
+		if (first == NULL) {
+			m->owner = NULL;
+
+			_ISR_Enable(level);
+		} else {
+			Thread_Control *new_owner =
+			    THREAD_RBTREE_NODE_TO_THREAD(first);
+
+			m->owner = new_owner;
+
+			_Thread_Disable_dispatch();
+			_ISR_Enable(level);
+
+			_Thread_Clear_state(new_owner, STATES_WAITING_FOR_MUTEX);
+
+			_Thread_Enable_dispatch();
+		}
+
+		if (!_Thread_Owns_resources(owner)
+		    && owner->real_priority != owner->current_priority) {
+			_Thread_Disable_dispatch();
+			_Thread_Change_priority(owner, owner->real_priority, true);
+			_Thread_Enable_dispatch();
+		}
+	}
+}
+
+static inline int
+rtems_bsd_mutex_owned(rtems_bsd_mutex *m)
+{
+
+	return (m->owner == _Thread_Get_executing());
+}
+
+static inline int
+rtems_bsd_mutex_recursed(rtems_bsd_mutex *m)
+{
+
+	return (m->nest_level);
+}
+
+static inline void
+rtems_bsd_mutex_destroy(struct lock_object *lock, rtems_bsd_mutex *m)
+{
+	BSD_ASSERT(_RBTree_Is_empty(&m->rivals));
+
+	if (rtems_bsd_mutex_owned(m)) {
+		m->nest_level = 0;
+		rtems_bsd_mutex_unlock(m);
+	}
+
+	lock_destroy(lock);
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_MUTEXIMPL_H_ */
diff --git a/rtemsbsd/include/machine/rtems-bsd-support.h b/rtemsbsd/include/machine/rtems-bsd-support.h
index de14892..49d396f 100644
--- a/rtemsbsd/include/machine/rtems-bsd-support.h
+++ b/rtemsbsd/include/machine/rtems-bsd-support.h
@@ -42,8 +42,6 @@
 
 #include <stdio.h>
 
-#include <rtems/chain.h>
-
 /* Debug */
 
 #define BSD_PRINTF(fmt, ...) printf("%s: " fmt, __func__, ##__VA_ARGS__)
@@ -54,16 +52,4 @@
 
 #define BSD_ASSERT_RV(rv) BSD_ASSERT((rv) == 0)
 
-extern rtems_chain_control rtems_bsd_lock_chain;
-
-extern rtems_chain_control rtems_bsd_mtx_chain;
-
-extern rtems_chain_control rtems_bsd_sx_chain;
-
-extern rtems_chain_control rtems_bsd_condvar_chain;
-
-extern rtems_chain_control rtems_bsd_callout_chain;
-
-extern rtems_chain_control rtems_bsd_malloc_chain;
-
 #endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_SUPPORT_H_ */
diff --git a/rtemsbsd/rtems/rtems-bsd-condvar.c b/rtemsbsd/rtems/rtems-bsd-condvar.c
index e64b470..ff2f9c3 100644
--- a/rtemsbsd/rtems/rtems-bsd-condvar.c
+++ b/rtemsbsd/rtems/rtems-bsd-condvar.c
@@ -39,153 +39,127 @@
 #include <machine/rtems-bsd-kernel-space.h>
 #include <machine/rtems-bsd-support.h>
 
-#include <rtems/score/objectimpl.h>
 #include <rtems/score/threaddispatch.h>
+#include <rtems/score/threadimpl.h>
 #include <rtems/score/threadqimpl.h>
-#include <rtems/posix/condimpl.h>
 
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
 #include <sys/systm.h>
 #include <rtems/bsd/sys/lock.h>
-#include <sys/mutex.h>
 #include <sys/condvar.h>
-
-RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_condvar_chain);
+#include <sys/mutex.h>
 
 void
 cv_init(struct cv *cv, const char *desc)
 {
-	int rv = pthread_cond_init(&cv->cv_id, NULL);
-
-	BSD_ASSERT_RV(rv);
 
 	cv->cv_description = desc;
-
-	rtems_chain_append(&rtems_bsd_condvar_chain, &cv->cv_node);
+	_Thread_queue_Initialize(&cv->cv_waiters, THREAD_QUEUE_DISCIPLINE_PRIORITY,
+	    STATES_WAITING_FOR_CONDITION_VARIABLE, EWOULDBLOCK);
 }
 
 void
 cv_destroy(struct cv *cv)
 {
-	int rv = pthread_cond_destroy(&cv->cv_id);
 
-	BSD_ASSERT_RV(rv);
-
-	rtems_chain_extract(&cv->cv_node);
+	BSD_ASSERT(_Thread_queue_First(&cv->cv_waiters) == NULL);
 }
 
-static int _cv_wait_support(struct cv *cv, struct lock_object *lock, int timo, bool relock)
+static int
+_cv_wait_support(struct cv *cv, struct lock_object *lock, Watchdog_Interval timo, bool relock)
 {
-	int eno = 0;
-	Objects_Locations location = OBJECTS_ERROR;
-	POSIX_Condition_variables_Control *pcv = _POSIX_Condition_variables_Get(&cv->cv_id, &location);
-
-	if (location == OBJECTS_LOCAL) {
-		struct lock_class *class = LOCK_CLASS(lock);
-		int lock_state;
-
-		if (pcv->Mutex != POSIX_CONDITION_VARIABLES_NO_MUTEX && pcv->Mutex != lock->lo_id) {
-			_Thread_Enable_dispatch();
-
-			BSD_ASSERT(false);
-
-			return EINVAL;
-		}
+	int error;
+	struct lock_class *class;
+	int lock_state;
+	Thread_Control *executing;
 
-		lock_state = (*class->lc_unlock)(lock);
+	_Thread_Disable_dispatch();
 
-		pcv->Mutex = lock->lo_id;
+	class = LOCK_CLASS(lock);
+	lock_state = (*class->lc_unlock)(lock);
 
-		_Thread_queue_Enter_critical_section(&pcv->Wait_queue);
-		_Thread_Executing->Wait.return_code = 0;
-		_Thread_Executing->Wait.queue = &pcv->Wait_queue;
-		_Thread_Executing->Wait.id = cv->cv_id;
+	_Thread_queue_Enter_critical_section(&cv->cv_waiters);
 
-		/* FIXME: Integer conversion */
-		_Thread_queue_Enqueue(&pcv->Wait_queue, _Thread_Executing, (Watchdog_Interval) timo);
+	executing = _Thread_Executing;
+	executing->Wait.return_code = 0;
+	executing->Wait.queue = &cv->cv_waiters;
 
-		DROP_GIANT();
+	_Thread_queue_Enqueue(&cv->cv_waiters, executing, timo);
 
-		_Thread_Enable_dispatch();
+	DROP_GIANT();
 
-		PICKUP_GIANT();
+	_Thread_Enable_dispatch();
 
-		eno = (int) _Thread_Executing->Wait.return_code;
-		if (eno != 0) {
-			if (eno == ETIMEDOUT) {
-				eno = EWOULDBLOCK;
-			} else {
-				BSD_ASSERT(false);
+	PICKUP_GIANT();
 
-				eno = EINVAL;
-			}
-		}
+	error = (int)executing->Wait.return_code;
 
-		if (relock) {
-			(*class->lc_lock)(lock, lock_state);
-		}
-
-		return eno;
+	if (relock) {
+		(*class->lc_lock)(lock, lock_state);
 	}
 
-	BSD_PANIC("unexpected object location");
+	return (error);
 }
 
 void
 _cv_wait(struct cv *cv, struct lock_object *lock)
 {
+
 	_cv_wait_support(cv, lock, 0, true);
 }
 
 void
 _cv_wait_unlock(struct cv *cv, struct lock_object *lock)
 {
+
 	_cv_wait_support(cv, lock, 0, false);
 }
 
 int
 _cv_timedwait(struct cv *cv, struct lock_object *lock, int timo)
 {
-	if (timo <= 0) {
+	if (timo <= 0)
 		timo = 1;
-	}
 
-	return _cv_wait_support(cv, lock, timo, true);
+	return (_cv_wait_support(cv, lock, (Watchdog_Interval)timo, true));
 }
 
 void
 cv_signal(struct cv *cv)
 {
-	int rv = pthread_cond_signal(&cv->cv_id);
 
-	BSD_ASSERT_RV(rv);
+	_Thread_Disable_dispatch();
+	_Thread_queue_Dequeue(&cv->cv_waiters);
+	_Thread_Enable_dispatch();
 }
 
 void
 cv_broadcastpri(struct cv *cv, int pri)
 {
-	int rv = 0;
 
-	/* FIXME: What to do with "pri"? */
+	_Thread_Disable_dispatch();
+
+	while (_Thread_queue_Dequeue(&cv->cv_waiters) != NULL) {
+		/* Again */
+	}
 
-	rv = pthread_cond_broadcast(&cv->cv_id);
-	BSD_ASSERT_RV(rv);
+	_Thread_Enable_dispatch();
 }
+
 int
-_cv_wait_sig(struct cv *cvp, struct lock_object *lock)
+_cv_wait_sig(struct cv *cv, struct lock_object *lock)
 {
-  /* XXX */
-	return _cv_wait_support(cvp, lock, 0, true);
+
+	return (_cv_wait_support(cv, lock, 0, true));
 }
 
 int
-_cv_timedwait_sig(struct cv *cvp, struct lock_object *lock, int timo)
+_cv_timedwait_sig(struct cv *cv, struct lock_object *lock, int timo)
 {
-  /* XXX */
-	if (timo <= 0) {
+
+	if (timo <= 0)
 		timo = 1;
-	}
 
-	return _cv_wait_support(cvp, lock, timo, true);
+	return (_cv_wait_support(cv, lock, (Watchdog_Interval)timo, true));
 }
diff --git a/rtemsbsd/rtems/rtems-bsd-mutex.c b/rtemsbsd/rtems/rtems-bsd-mutex.c
index b975b97..37cc04c 100644
--- a/rtemsbsd/rtems/rtems-bsd-mutex.c
+++ b/rtemsbsd/rtems/rtems-bsd-mutex.c
@@ -38,12 +38,7 @@
  */
 
 #include <machine/rtems-bsd-kernel-space.h>
-#include <machine/rtems-bsd-thread.h>
-#include <machine/rtems-bsd-support.h>
-
-#include <rtems/score/objectimpl.h>
-#include <rtems/rtems/attrimpl.h>
-#include <rtems/rtems/semimpl.h>
+#include <machine/rtems-bsd-muteximpl.h>
 
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
@@ -59,8 +54,6 @@ static int  owner_mtx(struct lock_object *lock, struct thread **owner);
 #endif
 static int  unlock_mtx(struct lock_object *lock);
 
-RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_mtx_chain);
-
 /*
  * Lock classes for sleep and spin mutexes.
  */
@@ -103,19 +96,15 @@ assert_mtx(struct lock_object *lock, int what)
 void
 lock_mtx(struct lock_object *lock, int how)
 {
-
-  mtx_lock((struct mtx *)lock);
+	mtx_lock((struct mtx *)lock);
 }
 
 int
 unlock_mtx(struct lock_object *lock)
 {
-  struct mtx *m;
+	mtx_unlock((struct mtx *)lock);
 
-  m = (struct mtx *)lock;
-  mtx_assert(m, MA_OWNED | MA_NOTRECURSED);
-  mtx_unlock(m);
-  return (0);
+	return (0);
 }
 
 
@@ -135,9 +124,6 @@ mtx_init(struct mtx *m, const char *name, const char *type, int opts)
 {
 	struct lock_class *class;
 	int flags;
-  rtems_status_code sc = RTEMS_SUCCESSFUL;
-  rtems_id id = RTEMS_ID_NONE;
-  rtems_attribute attr = RTEMS_LOCAL | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY;
 
 	/* Determine lock class and lock flags. */
 	if (opts & MTX_SPIN)
@@ -148,55 +134,26 @@ mtx_init(struct mtx *m, const char *name, const char *type, int opts)
 	if (opts & MTX_RECURSE)
 		flags |= LO_RECURSABLE;
 
-	lock_init(&m->lock_object, class, name, type, flags);
-
-	sc = rtems_semaphore_create(
-		rtems_build_name('_', 'M', 'T', 'X'),
-		1,
-		attr,
-		BSD_TASK_PRIORITY_RESOURCE_OWNER,
-		&id
-	);
-	BSD_ASSERT_SC(sc);
-
-  m->lock_object.lo_id = id;
-
-	rtems_chain_append(&rtems_bsd_mtx_chain, &m->lock_object.lo_node);
+	rtems_bsd_mutex_init(&m->lock_object, &m->mutex, class, name, type,
+	    flags);
 }
 
 void
 _mtx_lock_flags(struct mtx *m, int opts, const char *file, int line)
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-	sc = rtems_semaphore_obtain(m->lock_object.lo_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-	BSD_ASSERT_SC(sc);
+	rtems_bsd_mutex_lock(&m->lock_object, &m->mutex);
 }
 
 int
 _mtx_trylock(struct mtx *m, int opts, const char *file, int line)
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-	sc = rtems_semaphore_obtain(m->lock_object.lo_id, RTEMS_NO_WAIT, 0);
-	if (sc == RTEMS_SUCCESSFUL) {
-		return 1;
-	} else if (sc == RTEMS_UNSATISFIED) {
-		return 0;
-	} else {
-		BSD_ASSERT_SC(sc);
-
-		return 0;
-	}
+	return (rtems_bsd_mutex_trylock(&m->lock_object, &m->mutex));
 }
 
 void
 _mtx_unlock_flags(struct mtx *m, int opts, const char *file, int line)
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-	sc = rtems_semaphore_release(m->lock_object.lo_id);
-	BSD_ASSERT_SC(sc);
+	rtems_bsd_mutex_unlock(&m->mutex);
 }
 
 /*
@@ -238,38 +195,12 @@ _mtx_assert(struct mtx *m, int what, const char *file, int line)
 
 int mtx_owned(struct mtx *m)
 {
-	Objects_Locations location;
-	Semaphore_Control *sema = _Semaphore_Get(m->lock_object.lo_id, &location);
-
-	if (location == OBJECTS_LOCAL && !_Attributes_Is_counting_semaphore(sema->attribute_set)) {
-		int owned = sema->Core_control.mutex.holder == _Thread_Executing;
-
-		_Thread_Enable_dispatch();
-
-		return owned;
-	} else {
-		_Thread_Enable_dispatch();
-
-		BSD_PANIC("unexpected semaphore location or attributes");
-	}
+	return (rtems_bsd_mutex_owned(&m->mutex));
 }
 
 int mtx_recursed(struct mtx *m)
 {
-	Objects_Locations location;
-	Semaphore_Control *sema = _Semaphore_Get(m->lock_object.lo_id, &location);
-
-	if (location == OBJECTS_LOCAL && !_Attributes_Is_counting_semaphore(sema->attribute_set)) {
-		int recursed = sema->Core_control.mutex.nest_count != 0;
-
-		_Thread_Enable_dispatch();
-
-		return recursed;
-	} else {
-		_Thread_Enable_dispatch();
-
-		BSD_PANIC("unexpected semaphore location or attributes");
-	}
+	return (rtems_bsd_mutex_recursed(&m->mutex));
 }
 
 void
@@ -283,23 +214,8 @@ mtx_sysinit(void *arg)
 void
 mtx_destroy(struct mtx *m)
 {
-	rtems_status_code sc;
-
-	do {
-		sc = rtems_semaphore_delete(m->lock_object.lo_id);
-		if (sc == RTEMS_RESOURCE_IN_USE) {
-			BSD_ASSERT(mtx_owned(m));
-
-			mtx_unlock(m);
-		} else {
-			BSD_ASSERT_SC(sc);
-		}
-	} while (sc != RTEMS_SUCCESSFUL);
-
-	rtems_chain_extract(&m->lock_object.lo_node);
 
-	m->lock_object.lo_id = 0;
-	m->lock_object.lo_flags &= ~LO_INITIALIZED;
+	rtems_bsd_mutex_destroy(&m->lock_object, &m->mutex);
 }
 
 void
diff --git a/rtemsbsd/rtems/rtems-bsd-rwlock.c b/rtemsbsd/rtems/rtems-bsd-rwlock.c
index b85f374..b6540b5 100644
--- a/rtemsbsd/rtems/rtems-bsd-rwlock.c
+++ b/rtemsbsd/rtems/rtems-bsd-rwlock.c
@@ -46,17 +46,13 @@
  */
 
 #include <machine/rtems-bsd-kernel-space.h>
-#include <machine/rtems-bsd-thread.h>
-#include <machine/rtems-bsd-support.h>
-
-#include <rtems.h>
+#include <machine/rtems-bsd-muteximpl.h>
 
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
 #include <sys/systm.h>
 #include <rtems/bsd/sys/lock.h>
 #include <sys/rwlock.h>
-#include <sys/mutex.h>
 
 #ifndef INVARIANTS
 #define _rw_assert(rw, what, file, line)
@@ -83,8 +79,6 @@ struct lock_class lock_class_rw = {
 #endif
 };
 
-RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_rwlock_chain);
-
 void
 assert_rw(struct lock_object *lock, int what)
 {
@@ -94,29 +88,15 @@ assert_rw(struct lock_object *lock, int what)
 void
 lock_rw(struct lock_object *lock, int how)
 {
-  struct rwlock *rw;
-
-  rw = (struct rwlock *)lock;
-  if (how)
-    rw_wlock(rw);
-  else
-    rw_rlock(rw);
+  rw_wlock((struct rwlock *)lock);
 }
 
 int
 unlock_rw(struct lock_object *lock)
 {
-  struct rwlock *rw;
-
-  rw = (struct rwlock *)lock;
-  rw_assert(rw, RA_LOCKED | LA_NOTRECURSED);
-  if (rw->rw_lock & RW_LOCK_READ) {
-    rw_runlock(rw);
-    return (0);
-  } else {
-    rw_wunlock(rw);
-    return (1);
-  }
+  rw_unlock((struct rwlock *)lock);
+
+  return (0);
 }
 
 #ifdef KDTRACE_HOOKS
@@ -136,34 +116,20 @@ void
 rw_init_flags(struct rwlock *rw, const char *name, int opts)
 {
 	int flags;
-  rtems_status_code sc;
-  rtems_id id;
-  rtems_attribute attr = RTEMS_LOCAL | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY;
 
 	flags = LO_UPGRADABLE;
 	if (opts & RW_RECURSE)
 		flags |= LO_RECURSABLE;
 
-	lock_init(&rw->lock_object, &lock_class_rw, name, NULL, flags);
-
-  sc = rtems_semaphore_create(
-    rtems_build_name('_', '_', 'R', 'W'),
-    1,
-    attr,
-    BSD_TASK_PRIORITY_RESOURCE_OWNER,
-    &id
-  );
-  BSD_ASSERT_SC(sc);
-
-  rw->lock_object.lo_id = id;
-
-  rtems_chain_append(&rtems_bsd_rwlock_chain, &rw->lock_object.lo_node);
+	rtems_bsd_mutex_init(&rw->lock_object, &rw->mutex, &lock_class_rw,
+	    name, NULL, flags);
 }
 
 void
 rw_destroy(struct rwlock *rw)
 {
-  mtx_destroy((struct mtx *) rw);
+
+	rtems_bsd_mutex_destroy(&rw->lock_object, &rw->mutex);
 }
 
 void
@@ -185,55 +151,55 @@ rw_sysinit_flags(void *arg)
 int
 rw_wowned(struct rwlock *rw)
 {
-  return mtx_owned((struct mtx *) rw);
+	return (rtems_bsd_mutex_owned(&rw->mutex));
 }
 
 void
 _rw_wlock(struct rwlock *rw, const char *file, int line)
 {
-  _mtx_lock_flags((struct mtx *) rw, 0, file, line);
+	rtems_bsd_mutex_lock(&rw->lock_object, &rw->mutex);
 }
 
 int
 _rw_try_wlock(struct rwlock *rw, const char *file, int line)
 {
-  return _mtx_trylock((struct mtx *) rw, 0, file, line);
+	return (rtems_bsd_mutex_trylock(&rw->lock_object, &rw->mutex));
 }
 
 void
 _rw_wunlock(struct rwlock *rw, const char *file, int line)
 {
-  _mtx_unlock_flags((struct mtx *) rw, 0, file, line);
+	rtems_bsd_mutex_unlock(&rw->mutex);
 }
 
 void
 _rw_rlock(struct rwlock *rw, const char *file, int line)
 {
-  _mtx_lock_flags((struct mtx *) rw, 0, file, line);
+	rtems_bsd_mutex_lock(&rw->lock_object, &rw->mutex);
 }
 
 int
 _rw_try_rlock(struct rwlock *rw, const char *file, int line)
 {
-  return _mtx_trylock((struct mtx *) rw, 0, file, line);
+	return (rtems_bsd_mutex_trylock(&rw->lock_object, &rw->mutex));
 }
 
 void
 _rw_runlock(struct rwlock *rw, const char *file, int line)
 {
-  _mtx_unlock_flags((struct mtx *) rw, 0, file, line);
+	rtems_bsd_mutex_unlock(&rw->mutex);
 }
 
 int
 _rw_try_upgrade(struct rwlock *rw, const char *file, int line)
 {
-  return 1;
+	return (1);
 }
 
 void
 _rw_downgrade(struct rwlock *rw, const char *file, int line)
 {
-  /* Nothing to do */
+	/* Nothing to do */
 }
 
 #ifdef INVARIANT_SUPPORT
diff --git a/rtemsbsd/rtems/rtems-bsd-shell.c b/rtemsbsd/rtems/rtems-bsd-shell.c
index 2fa1aaa..7ccb170 100644
--- a/rtemsbsd/rtems/rtems-bsd-shell.c
+++ b/rtemsbsd/rtems/rtems-bsd-shell.c
@@ -44,67 +44,12 @@
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
 #include <sys/systm.h>
-#include <rtems/bsd/sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/callout.h>
-#include <sys/condvar.h>
 #include <sys/proc.h>
 
 #include <rtems/bsd/bsd.h>
 #include <rtems/shell.h>
 
 static void
-rtems_bsd_dump_mtx(void)
-{
-	rtems_chain_control *chain = &rtems_bsd_mtx_chain;
-	rtems_chain_node *node = rtems_chain_first(chain);
-
-	printf("mtx dump:\n");
-
-	while (!rtems_chain_is_tail(chain, node)) {
-		struct lock_object *lo = (struct lock_object *) node;
-
-		printf("\t%s: 0x%08x\n", lo->lo_name, lo->lo_id);
-
-		node = rtems_chain_next(node);
-	}
-}
-
-static void
-rtems_bsd_dump_sx(void)
-{
-	rtems_chain_control *chain = &rtems_bsd_sx_chain;
-	rtems_chain_node *node = rtems_chain_first(chain);
-
-	printf("sx dump:\n");
-
-	while (!rtems_chain_is_tail(chain, node)) {
-		struct lock_object *lo = (struct lock_object *) node;
-
-		printf("\t%s: 0x%08x\n", lo->lo_name, lo->lo_id);
-
-		node = rtems_chain_next(node);
-	}
-}
-
-static void
-rtems_bsd_dump_condvar(void)
-{
-	rtems_chain_control *chain = &rtems_bsd_condvar_chain;
-	rtems_chain_node *node = rtems_chain_first(chain);
-
-	printf("condvar dump:\n");
-
-	while (!rtems_chain_is_tail(chain, node)) {
-		struct cv *cv = (struct cv *) node;
-
-		printf("\t%s: 0x%08x\n", cv->cv_description, cv->cv_id);
-
-		node = rtems_chain_next(node);
-	}
-}
-
-static void
 rtems_bsd_dump_thread(void)
 {
 	const rtems_chain_control *chain = &rtems_bsd_thread_chain;
@@ -122,7 +67,7 @@ rtems_bsd_dump_thread(void)
 }
 
 static const char rtems_bsd_usage [] =
-	"bsd {all|mtx|sx|condvar|thread|callout}";
+	"bsd {all|condvar|thread|callout}";
 
 #define CMP(s) all || strcasecmp(argv [1], s) == 0
 
@@ -138,18 +83,6 @@ rtems_bsd_info(int argc, char **argv)
 			all = true;
 		}
 
-		if (CMP("mtx")) {
-			rtems_bsd_dump_mtx();
-			usage = false;
-		}
-		if (CMP("sx")) {
-			rtems_bsd_dump_sx();
-			usage = false;
-		}
-		if (CMP("condvar")) {
-			rtems_bsd_dump_condvar();
-			usage = false;
-		}
 		if (CMP("thread")) {
 			rtems_bsd_dump_thread();
 			usage = false;
diff --git a/rtemsbsd/rtems/rtems-bsd-sx.c b/rtemsbsd/rtems/rtems-bsd-sx.c
index 3d0e79e..46ab2d1 100644
--- a/rtemsbsd/rtems/rtems-bsd-sx.c
+++ b/rtemsbsd/rtems/rtems-bsd-sx.c
@@ -38,11 +38,7 @@
  */
 
 #include <machine/rtems-bsd-kernel-space.h>
-#include <machine/rtems-bsd-support.h>
-
-#include <rtems/score/objectimpl.h>
-#include <rtems/rtems/attrimpl.h>
-#include <rtems/rtems/semimpl.h>
+#include <machine/rtems-bsd-muteximpl.h>
 
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
@@ -75,8 +71,6 @@ struct lock_class lock_class_sx = {
 #endif
 };
 
-RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_sx_chain);
-
 void
 assert_sx(struct lock_object *lock, int what)
 {
@@ -86,29 +80,15 @@ assert_sx(struct lock_object *lock, int what)
 void
 lock_sx(struct lock_object *lock, int how)
 {
-  struct sx *sx;
-
-  sx = (struct sx *)lock;
-  if (how)
-    sx_xlock(sx);
-  else
-    sx_slock(sx);
+	sx_xlock((struct sx *)lock);
 }
 
 int
 unlock_sx(struct lock_object *lock)
 {
-  struct sx *sx;
+	sx_xunlock((struct sx *)lock);
 
-  sx = (struct sx *)lock;
-  sx_assert(sx, SA_LOCKED | SA_NOTRECURSED);
-  if (sx_xlocked(sx)) {
-    sx_xunlock(sx);
-    return (1);
-  } else {
-    sx_sunlock(sx);
-    return (0);
-  }
+	return (0);
 }
 
 #ifdef KDTRACE_HOOKS
@@ -136,89 +116,46 @@ void
 sx_init_flags(struct sx *sx, const char *description, int opts)
 {
 	int flags;
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-	rtems_id id = RTEMS_ID_NONE;
-	rtems_attribute attr = RTEMS_LOCAL | RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE;
 
 	flags = LO_SLEEPABLE | LO_UPGRADABLE;
 	if (opts & SX_RECURSE)
 		flags |= LO_RECURSABLE;
 
-	lock_init(&sx->lock_object, &lock_class_sx, description, NULL, flags);
-
-	sc = rtems_semaphore_create(
-		rtems_build_name( '_', 'S', 'X', ' '),
-		1,
-		attr,
-		0,
-		&id
-	);
-	BSD_ASSERT_SC(sc);
-
-  sx->lock_object.lo_id = id;
-
-	rtems_chain_append(&rtems_bsd_sx_chain, &sx->lock_object.lo_node);
+	rtems_bsd_mutex_init(&sx->lock_object, &sx->mutex, &lock_class_sx,
+	    description, NULL, flags);
 }
 
 void
 sx_destroy(struct sx *sx)
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-	sc = rtems_semaphore_delete( sx->lock_object.lo_id);
-	BSD_ASSERT_SC(sc);
-
-	rtems_chain_extract(&sx->lock_object.lo_node);
 
-  sx->lock_object.lo_id = 0;
-  sx->lock_object.lo_flags &= ~LO_INITIALIZED;
+	rtems_bsd_mutex_destroy(&sx->lock_object, &sx->mutex);
 }
 
 int
 _sx_xlock(struct sx *sx, int opts, const char *file, int line)
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
+	rtems_bsd_mutex_lock(&sx->lock_object, &sx->mutex);
 
-	#warning "SX_INTERRUPTIBLE NOT SUPPORTED YET"
-	/* BSD_ASSERT((opts & SX_INTERRUPTIBLE) == 0); */
-        BSD_ASSERT(!rtems_interrupt_is_in_progress());
-        
-	sc = rtems_semaphore_obtain( sx->lock_object.lo_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-	BSD_ASSERT_SC(sc);
-
-	return 0;
+	return (0);
 }
 
 int
 _sx_try_xlock(struct sx *sx, const char *file, int line)
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-	sc = rtems_semaphore_obtain( sx->lock_object.lo_id, RTEMS_NO_WAIT, 0);
-	if (sc == RTEMS_SUCCESSFUL) {
-		return 1;
-	} else if (sc == RTEMS_UNSATISFIED) {
-		return 0;
-	} else {
-		BSD_ASSERT_SC(sc);
-
-		return 0;
-	}
+	return (rtems_bsd_mutex_trylock(&sx->lock_object, &sx->mutex));
 }
 
 void
 _sx_xunlock(struct sx *sx, const char *file, int line)
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-	sc = rtems_semaphore_release( sx->lock_object.lo_id);
-	BSD_ASSERT_SC(sc);
+	rtems_bsd_mutex_unlock(&sx->mutex);
 }
 
 int
 _sx_try_upgrade(struct sx *sx, const char *file, int line)
 {
-	return 1;
+	return (1);
 }
 
 void
@@ -322,18 +259,5 @@ _sx_assert(struct sx *sx, int what, const char *file, int line)
 int
 sx_xlocked(struct sx *sx)
 {
-	Objects_Locations location;
-	Semaphore_Control *sema = _Semaphore_Get(sx->lock_object.lo_id, &location);
-
-	if (location == OBJECTS_LOCAL && !_Attributes_Is_counting_semaphore(sema->attribute_set)) {
-		int xlocked = sema->Core_control.mutex.holder == _Thread_Executing;
-
-		_Thread_Enable_dispatch();
-
-		return xlocked;
-	} else {
-		_Thread_Enable_dispatch();
-
-		BSD_PANIC("unexpected semaphore location or attributes");
-	}
+	return (rtems_bsd_mutex_owned(&sx->mutex));
 }
diff --git a/testsuite/condvar01/test_main.c b/testsuite/condvar01/test_main.c
new file mode 100644
index 0000000..53c9815
--- /dev/null
+++ b/testsuite/condvar01/test_main.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/rtems-bsd-kernel-space.h>
+
+#include <rtems/bsd/sys/param.h>
+#include <rtems/bsd/sys/types.h>
+#include <sys/systm.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems/libcsupport.h>
+#include <rtems.h>
+
+#define TEST_NAME "LIBBSD CONDVAR 1"
+
+#define PRIO_MASTER 3
+
+#define EVENT_LOCK RTEMS_EVENT_0
+
+#define EVENT_UNLOCK RTEMS_EVENT_1
+
+#define EVENT_WAIT RTEMS_EVENT_2
+
+#define EVENT_WAIT_SIG RTEMS_EVENT_3
+
+#define EVENT_WAIT_UNLOCK RTEMS_EVENT_4
+
+#define EVENT_TIMEDWAIT RTEMS_EVENT_5
+
+#define EVENT_TIMEDWAIT_SIG RTEMS_EVENT_6
+
+#define WORKER_COUNT 2
+
+typedef struct {
+	struct mtx mtx;
+	struct cv cv;
+	int rv;
+	int timo;
+	rtems_id worker_task[WORKER_COUNT];
+	bool done[WORKER_COUNT];
+} test_context;
+
+static test_context test_instance;
+
+static const rtems_task_priority prio_worker[2] = { 2, 1 };
+
+static void
+set_self_prio(rtems_task_priority prio)
+{
+	rtems_status_code sc;
+
+	sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
+	assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+worker_task(rtems_task_argument index)
+{
+	test_context *ctx = &test_instance;
+	struct mtx *mtx = &ctx->mtx;
+	struct cv *cv = &ctx->cv;
+
+	while (true) {
+		rtems_status_code sc;
+		rtems_event_set events;
+
+		sc = rtems_event_receive(
+			RTEMS_ALL_EVENTS,
+			RTEMS_EVENT_ANY | RTEMS_WAIT,
+			RTEMS_NO_TIMEOUT,
+			&events
+		);
+		assert(sc == RTEMS_SUCCESSFUL);
+
+		if ((events & EVENT_LOCK) != 0) {
+			mtx_lock(mtx);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_UNLOCK) != 0) {
+			mtx_unlock(mtx);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_WAIT) != 0) {
+			cv_wait(cv, mtx);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_WAIT_SIG) != 0) {
+			int rv = cv_wait_sig(cv, mtx);
+			assert(rv == 0);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_WAIT_UNLOCK) != 0) {
+			cv_wait_unlock(cv, mtx);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_TIMEDWAIT) != 0) {
+			ctx->rv = cv_timedwait(cv, mtx, ctx->timo);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_TIMEDWAIT_SIG) != 0) {
+			ctx->rv = cv_timedwait_sig(cv, mtx, ctx->timo);
+			ctx->done[index] = true;
+		}
+	}
+}
+
+static void
+send_events(test_context *ctx, rtems_event_set events, size_t index)
+{
+	rtems_status_code sc;
+
+	sc = rtems_event_send(ctx->worker_task[index], events);
+	assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+start_worker(test_context *ctx)
+{
+	size_t i;
+
+	for (i = 0; i < WORKER_COUNT; ++i) {
+		rtems_status_code sc;
+
+		sc = rtems_task_create(
+			rtems_build_name('W', 'O', 'R', 'K'),
+			prio_worker[i],
+			RTEMS_MINIMUM_STACK_SIZE,
+			RTEMS_DEFAULT_MODES,
+			RTEMS_FLOATING_POINT,
+			&ctx->worker_task[i]
+		);
+		assert(sc == RTEMS_SUCCESSFUL);
+
+		sc = rtems_task_start(
+			ctx->worker_task[i],
+			worker_task,
+			i
+		);
+		assert(sc == RTEMS_SUCCESSFUL);
+	}
+}
+
+static void
+delete_worker(test_context *ctx)
+{
+	size_t i;
+
+	for (i = 0; i < WORKER_COUNT; ++i) {
+		rtems_status_code sc;
+
+		sc = rtems_task_delete(ctx->worker_task[i]);
+		assert(sc == RTEMS_SUCCESSFUL);
+	}
+}
+
+static void
+test_cv_wait_signal(test_context *ctx, rtems_event_set event, const char *name)
+{
+	struct mtx *mtx = &ctx->mtx;
+	struct cv *cv = &ctx->cv;
+	size_t low = 0;
+	size_t high = 1;
+
+	printf("test cv %s signal\n", name);
+
+	mtx_lock(mtx);
+	mtx_unlock(mtx);
+
+	ctx->timo = 0;
+
+	ctx->done[low] = false;
+	send_events(ctx, EVENT_LOCK, low);
+	assert(ctx->done[low]);
+
+	ctx->done[high] = false;
+	send_events(ctx, EVENT_LOCK, high);
+	assert(!ctx->done[high]);
+
+	ctx->done[low] = false;
+	send_events(ctx, event, low);
+	assert(!ctx->done[low]);
+	assert(ctx->done[high]);
+
+	ctx->done[low] = false;
+	ctx->done[high] = false;
+	send_events(ctx, event, high);
+	assert(!ctx->done[low]);
+	assert(!ctx->done[high]);
+
+	cv_signal(cv);
+	assert(!ctx->done[low]);
+	assert(ctx->done[high]);
+
+	if (event != EVENT_WAIT_UNLOCK) {
+		cv_signal(cv);
+		assert(!ctx->done[low]);
+
+		ctx->done[high] = false;
+		send_events(ctx, EVENT_UNLOCK, high);
+		assert(ctx->done[high]);
+		assert(ctx->done[low]);
+
+		ctx->done[low] = false;
+		send_events(ctx, EVENT_UNLOCK, low);
+		assert(ctx->done[low]);
+	} else {
+		cv_signal(cv);
+		assert(ctx->done[low]);
+	}
+
+	mtx_lock(mtx);
+	mtx_unlock(mtx);
+}
+
+static void
+test_cv_wait_broadcast(test_context *ctx, rtems_event_set event, const char *name)
+{
+	struct mtx *mtx = &ctx->mtx;
+	struct cv *cv = &ctx->cv;
+	size_t low = 0;
+	size_t high = 1;
+
+	printf("test cv %s broadcast\n", name);
+
+	mtx_lock(mtx);
+	mtx_unlock(mtx);
+
+	ctx->timo = 0;
+
+	ctx->done[low] = false;
+	send_events(ctx, EVENT_LOCK, low);
+	assert(ctx->done[low]);
+
+	ctx->done[high] = false;
+	send_events(ctx, EVENT_LOCK, high);
+	assert(!ctx->done[high]);
+
+	ctx->done[low] = false;
+	send_events(ctx, event, low);
+	assert(!ctx->done[low]);
+	assert(ctx->done[high]);
+
+	ctx->done[low] = false;
+	ctx->done[high] = false;
+	send_events(ctx, event, high);
+	assert(!ctx->done[low]);
+	assert(!ctx->done[high]);
+
+	if (event != EVENT_WAIT_UNLOCK) {
+		cv_broadcast(cv);
+		assert(!ctx->done[low]);
+
+		ctx->done[high] = false;
+		send_events(ctx, EVENT_UNLOCK, high);
+		assert(ctx->done[high]);
+		assert(ctx->done[low]);
+
+		ctx->done[low] = false;
+		send_events(ctx, EVENT_UNLOCK, low);
+		assert(ctx->done[low]);
+	} else {
+		cv_broadcast(cv);
+		assert(ctx->done[low]);
+		assert(ctx->done[high]);
+	}
+
+	mtx_lock(mtx);
+	mtx_unlock(mtx);
+}
+
+static void
+test_cv_wait(test_context *ctx, rtems_event_set event, const char *name)
+{
+	test_cv_wait_signal(ctx, event, name);
+	test_cv_wait_broadcast(ctx, event, name);
+}
+
+static void
+test_cv_wait_timeout(test_context *ctx)
+{
+	size_t index = 0;
+	rtems_status_code sc;
+
+	puts("test cv wait timeout");
+
+	ctx->timo = 2;
+
+	ctx->done[index] = false;
+	send_events(ctx, EVENT_LOCK, index);
+	assert(ctx->done[index]);
+
+	ctx->done[index] = false;
+	ctx->rv = 0;
+	send_events(ctx, EVENT_TIMEDWAIT, index);
+	assert(!ctx->done[index]);
+
+	sc = rtems_task_wake_after(ctx->timo);
+	assert(sc == RTEMS_SUCCESSFUL);
+	assert(ctx->done[index]);
+	assert(ctx->rv == EWOULDBLOCK);
+
+	ctx->done[index] = false;
+	ctx->rv = 0;
+	send_events(ctx, EVENT_TIMEDWAIT_SIG, index);
+	assert(!ctx->done[index]);
+
+	sc = rtems_task_wake_after(ctx->timo);
+	assert(sc == RTEMS_SUCCESSFUL);
+	assert(ctx->done[index]);
+	assert(ctx->rv == EWOULDBLOCK);
+
+	ctx->done[index] = false;
+	send_events(ctx, EVENT_UNLOCK, index);
+	assert(ctx->done[index]);
+}
+
+static void
+alloc_basic_resources(void)
+{
+	curthread;
+}
+
+static void
+test_main(void)
+{
+	test_context *ctx = &test_instance;
+	rtems_resource_snapshot snapshot;
+
+	alloc_basic_resources();
+
+	rtems_resource_snapshot_take(&snapshot);
+
+	cv_init(&ctx->cv, "test");
+	assert(strcmp(cv_wmesg(&ctx->cv), "test") == 0);
+
+	set_self_prio(PRIO_MASTER);
+	start_worker(ctx);
+
+	test_cv_wait(ctx, EVENT_WAIT, "wait");
+	test_cv_wait(ctx, EVENT_WAIT_SIG, "wait sig");
+	test_cv_wait(ctx, EVENT_WAIT_UNLOCK, "wait unlock");
+	test_cv_wait(ctx, EVENT_TIMEDWAIT, "timed wait");
+	test_cv_wait(ctx, EVENT_TIMEDWAIT_SIG, "timed wait sig");
+
+	test_cv_wait_timeout(ctx);
+
+	delete_worker(ctx);
+	cv_destroy(&ctx->cv);
+
+	assert(rtems_resource_snapshot_check(&snapshot));
+
+	exit(0);
+}
+
+#include <rtems/bsd/test/default-init.h>
diff --git a/testsuite/mutex01/test_main.c b/testsuite/mutex01/test_main.c
new file mode 100644
index 0000000..504d80a
--- /dev/null
+++ b/testsuite/mutex01/test_main.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/rtems-bsd-kernel-space.h>
+
+#include <rtems/bsd/sys/param.h>
+#include <rtems/bsd/sys/types.h>
+#include <sys/systm.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/mutex.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems/libcsupport.h>
+#include <rtems.h>
+
+#define TEST_NAME "LIBBSD MUTEX 1"
+
+#define PRIO_MASTER 3
+
+#define EVENT_LOCK RTEMS_EVENT_0
+
+#define EVENT_TRY_LOCK RTEMS_EVENT_1
+
+#define EVENT_UNLOCK RTEMS_EVENT_2
+
+#define EVENT_SLEEP RTEMS_EVENT_3
+
+#define WORKER_COUNT 2
+
+typedef struct {
+	struct mtx mtx;
+	struct mtx mtx2;
+	int rv;
+	int timo;
+	rtems_id worker_task[WORKER_COUNT];
+	bool done[WORKER_COUNT];
+} test_context;
+
+static test_context test_instance;
+
+static const rtems_task_priority prio_worker[2] = { 2, 1 };
+
+static void
+set_self_prio(rtems_task_priority prio)
+{
+	rtems_status_code sc;
+
+	sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
+	assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static rtems_task_priority
+get_self_prio(void)
+{
+	rtems_status_code sc;
+	rtems_task_priority prio;
+
+	sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
+	assert(sc == RTEMS_SUCCESSFUL);
+
+	return prio;
+}
+
+static void
+worker_task(rtems_task_argument index)
+{
+	test_context *ctx = &test_instance;
+	struct mtx *mtx = &ctx->mtx;
+
+	while (true) {
+		rtems_status_code sc;
+		rtems_event_set events;
+
+		sc = rtems_event_receive(
+			RTEMS_ALL_EVENTS,
+			RTEMS_EVENT_ANY | RTEMS_WAIT,
+			RTEMS_NO_TIMEOUT,
+			&events
+		);
+		assert(sc == RTEMS_SUCCESSFUL);
+
+		if ((events & EVENT_LOCK) != 0) {
+			mtx_lock(mtx);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_TRY_LOCK) != 0) {
+			ctx->rv = mtx_trylock(mtx);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_UNLOCK) != 0) {
+			mtx_unlock(mtx);
+			ctx->done[index] = true;
+		}
+
+		if ((events & EVENT_SLEEP) != 0) {
+			ctx->rv = mtx_sleep(ctx, mtx, 0, "worker", ctx->timo);
+			ctx->done[index] = true;
+		}
+	}
+}
+
+static void
+send_events(test_context *ctx, rtems_event_set events, size_t index)
+{
+	rtems_status_code sc;
+
+	sc = rtems_event_send(ctx->worker_task[index], events);
+	assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+start_worker(test_context *ctx)
+{
+	size_t i;
+
+	for (i = 0; i < WORKER_COUNT; ++i) {
+		rtems_status_code sc;
+
+		sc = rtems_task_create(
+			rtems_build_name('W', 'O', 'R', 'K'),
+			prio_worker[i],
+			RTEMS_MINIMUM_STACK_SIZE,
+			RTEMS_DEFAULT_MODES,
+			RTEMS_FLOATING_POINT,
+			&ctx->worker_task[i]
+		);
+		assert(sc == RTEMS_SUCCESSFUL);
+
+		sc = rtems_task_start(
+			ctx->worker_task[i],
+			worker_task,
+			i
+		);
+		assert(sc == RTEMS_SUCCESSFUL);
+	}
+}
+
+static void
+delete_worker(test_context *ctx)
+{
+	size_t i;
+
+	for (i = 0; i < WORKER_COUNT; ++i) {
+		rtems_status_code sc;
+
+		sc = rtems_task_delete(ctx->worker_task[i]);
+		assert(sc == RTEMS_SUCCESSFUL);
+	}
+}
+
+static void
+test_mtx_non_recursive(test_context *ctx)
+{
+	struct mtx *mtx = &ctx->mtx;
+
+	puts("test mtx non-recursive");
+
+	assert(!mtx_initialized(mtx));
+	mtx_init(mtx, "test", NULL, MTX_DEF);
+	assert(mtx_initialized(mtx));
+
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_lock(mtx);
+
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	mtx_unlock(mtx);
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	mtx_destroy(mtx);
+	assert(!mtx_initialized(mtx));
+}
+
+static void
+test_mtx_recursive(test_context *ctx)
+{
+	struct mtx *mtx = &ctx->mtx;
+
+	puts("test mtx recursive");
+
+	assert(!mtx_initialized(mtx));
+	mtx_init(mtx, "test", NULL, MTX_DEF | MTX_RECURSE);
+	assert(mtx_initialized(mtx));
+
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_lock(mtx);
+
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_lock(mtx);
+
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 1);
+	mtx_lock(mtx);
+
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 2);
+
+	mtx_unlock(mtx);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 1);
+
+	mtx_unlock(mtx);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	mtx_unlock(mtx);
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	mtx_destroy(mtx);
+	assert(!mtx_initialized(mtx));
+}
+
+static void
+test_mtx_trylock(test_context *ctx)
+{
+	size_t index = 0;
+	struct mtx *mtx = &ctx->mtx;
+	int ok;
+
+	puts("test mtx try lock");
+
+	assert(!mtx_initialized(mtx));
+	mtx_init(mtx, "test", NULL, MTX_DEF);
+	assert(mtx_initialized(mtx));
+
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	ok = mtx_trylock(mtx);
+	assert(ok != 0);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	mtx_unlock(mtx);
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_lock(mtx);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	ctx->done[index] = false;
+	ctx->rv = 1;
+	send_events(ctx, EVENT_TRY_LOCK, index);
+	assert(ctx->done[index]);
+	assert(ctx->rv == 0);
+
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_unlock(mtx);
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	mtx_destroy(mtx);
+	assert(!mtx_initialized(mtx));
+}
+
+static void
+test_mtx_lock(test_context *ctx)
+{
+	struct mtx *mtx = &ctx->mtx;
+	struct mtx *mtx2 = &ctx->mtx2;
+	size_t low = 0;
+	size_t high = 1;
+
+	puts("test mtx lock");
+
+	assert(!mtx_initialized(mtx));
+	mtx_init(mtx, "test", NULL, MTX_DEF);
+	assert(mtx_initialized(mtx));
+
+	assert(!mtx_initialized(mtx2));
+	mtx_init(mtx2, "test 2", NULL, MTX_DEF);
+	assert(mtx_initialized(mtx2));
+
+	/* Resource count one */
+
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_lock(mtx);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	assert(get_self_prio() == PRIO_MASTER);
+
+	ctx->done[low] = false;
+	ctx->done[high] = false;
+
+	send_events(ctx, EVENT_LOCK, low);
+	assert(!ctx->done[low]);
+	assert(!ctx->done[high]);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	assert(get_self_prio() == prio_worker[low]);
+
+	send_events(ctx, EVENT_LOCK, high);
+	assert(!ctx->done[low]);
+	assert(!ctx->done[high]);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	assert(get_self_prio() == prio_worker[high]);
+
+	mtx_unlock(mtx);
+	assert(!ctx->done[low]);
+	assert(ctx->done[high]);
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	assert(get_self_prio() == PRIO_MASTER);
+
+	ctx->done[high] = false;
+	send_events(ctx, EVENT_UNLOCK, high);
+	assert(ctx->done[low]);
+	assert(ctx->done[high]);
+
+	ctx->done[low] = false;
+	send_events(ctx, EVENT_UNLOCK, low);
+	assert(ctx->done[low]);
+
+	/* Resource count two */
+
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_lock(mtx);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	assert(get_self_prio() == PRIO_MASTER);
+
+	assert(!mtx_owned(mtx2));
+	assert(mtx_recursed(mtx2) == 0);
+	mtx_lock(mtx2);
+	assert(mtx_owned(mtx2));
+	assert(mtx_recursed(mtx2) == 0);
+	assert(get_self_prio() == PRIO_MASTER);
+
+	ctx->done[low] = false;
+	send_events(ctx, EVENT_LOCK, low);
+	assert(!ctx->done[low]);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	assert(get_self_prio() == prio_worker[low]);
+
+	mtx_unlock(mtx2);
+	assert(!mtx_owned(mtx2));
+	assert(mtx_recursed(mtx2) == 0);
+	assert(get_self_prio() == prio_worker[low]);
+
+	mtx_unlock(mtx);
+	assert(ctx->done[low]);
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	assert(get_self_prio() == PRIO_MASTER);
+
+	ctx->done[low] = false;
+	send_events(ctx, EVENT_UNLOCK, low);
+	assert(ctx->done[low]);
+
+	mtx_destroy(mtx2);
+	assert(!mtx_initialized(mtx2));
+
+	mtx_destroy(mtx);
+	assert(!mtx_initialized(mtx));
+}
+
+static void
+test_mtx_sleep_with_lock(test_context *ctx)
+{
+	size_t index = 0;
+	struct mtx *mtx = &ctx->mtx;
+
+	puts("test mtx sleep with lock");
+
+	assert(!mtx_initialized(mtx));
+	mtx_init(mtx, "test", NULL, MTX_DEF);
+	assert(mtx_initialized(mtx));
+
+	ctx->done[index] = false;
+	send_events(ctx, EVENT_LOCK, index);
+	assert(ctx->done[index]);
+
+	ctx->done[index] = false;
+	ctx->timo = 0;
+	send_events(ctx, EVENT_SLEEP, index);
+	assert(!ctx->done[index]);
+
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+	mtx_lock(mtx);
+	assert(mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	wakeup(ctx);
+	assert(!ctx->done[index]);
+
+	mtx_unlock(mtx);
+	assert(ctx->done[index]);
+	assert(!mtx_owned(mtx));
+	assert(mtx_recursed(mtx) == 0);
+
+	ctx->done[index] = false;
+	send_events(ctx, EVENT_UNLOCK, index);
+	assert(ctx->done[index]);
+
+	mtx_destroy(mtx);
+	assert(!mtx_initialized(mtx));
+}
+
+static void
+test_mtx_sleep_timeout(test_context *ctx)
+{
+	size_t index = 0;
+	struct mtx *mtx = &ctx->mtx;
+	rtems_status_code sc;
+
+	puts("test mtx sleep timeout");
+
+	assert(!mtx_initialized(mtx));
+	mtx_init(mtx, "test", NULL, MTX_DEF);
+	assert(mtx_initialized(mtx));
+
+	ctx->done[index] = false;
+	send_events(ctx, EVENT_LOCK, index);
+	assert(ctx->done[index]);
+
+	ctx->done[index] = false;
+	ctx->timo = 2;
+	send_events(ctx, EVENT_SLEEP, index);
+	assert(!ctx->done[index]);
+
+	sc = rtems_task_wake_after(ctx->timo);
+	assert(sc == RTEMS_SUCCESSFUL);
+	assert(ctx->done[index]);
+
+	ctx->done[index] = false;
+	send_events(ctx, EVENT_UNLOCK, index);
+	assert(ctx->done[index]);
+
+	mtx_destroy(mtx);
+	assert(!mtx_initialized(mtx));
+}
+
+static void
+alloc_basic_resources(void)
+{
+	curthread;
+}
+
+static void
+test_main(void)
+{
+	test_context *ctx = &test_instance;
+	rtems_resource_snapshot snapshot_0;
+	rtems_resource_snapshot snapshot_1;
+
+	alloc_basic_resources();
+
+	rtems_resource_snapshot_take(&snapshot_0);
+
+	set_self_prio(PRIO_MASTER);
+	start_worker(ctx);
+
+	rtems_resource_snapshot_take(&snapshot_1);
+
+	test_mtx_non_recursive(ctx);
+	test_mtx_recursive(ctx);
+	test_mtx_trylock(ctx);
+	test_mtx_lock(ctx);
+
+	assert(rtems_resource_snapshot_check(&snapshot_1));
+
+	test_mtx_sleep_with_lock(ctx);
+	test_mtx_sleep_timeout(ctx);
+
+	delete_worker(ctx);
+
+	assert(rtems_resource_snapshot_check(&snapshot_0));
+
+	exit(0);
+}
+
+#include <rtems/bsd/test/default-init.h>
diff --git a/testsuite/rwlock01/test_main.c b/testsuite/rwlock01/test_main.c
index fc4b269..3e121c3 100644
--- a/testsuite/rwlock01/test_main.c
+++ b/testsuite/rwlock01/test_main.c
@@ -188,9 +188,6 @@ test_rw_non_recursive(test_context *ctx)
 	rw_rlock(rw);
 	/* FIXME: We use a mutex implementation */
 	assert(rw_wowned(rw));
-	/* FIXME: We always allow recursion */
-	rw_rlock(rw);
-	rw_runlock(rw);
 	rw_runlock(rw);
 
 	rw_rlock(rw);
@@ -228,9 +225,6 @@ test_rw_non_recursive(test_context *ctx)
 
 	rw_wlock(rw);
 	assert(rw_wowned(rw));
-	/* FIXME: We always allow recursion */
-	rw_wlock(rw);
-	rw_wunlock(rw);
 	rw_wunlock(rw);
 
 	rw_wlock(rw);



More information about the vc mailing list