summaryrefslogtreecommitdiffstats
path: root/rtemsbsd/include/machine/rtems-bsd-muteximpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'rtemsbsd/include/machine/rtems-bsd-muteximpl.h')
-rw-r--r--rtemsbsd/include/machine/rtems-bsd-muteximpl.h220
1 files changed, 220 insertions, 0 deletions
diff --git a/rtemsbsd/include/machine/rtems-bsd-muteximpl.h b/rtemsbsd/include/machine/rtems-bsd-muteximpl.h
new file mode 100644
index 00000000..69b42eb6
--- /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@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_ */