[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