diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-09-22 13:42:26 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-09-23 10:03:10 +0200 |
commit | be43b79fcabb7551677e2d27c75e2a500e2ba622 (patch) | |
tree | adacb76593743ee5bf58d0ea5df2db97880b5d5a /rtemsbsd/include/machine/rtems-bsd-muteximpl.h | |
parent | Include missing header file (diff) | |
download | rtems-libbsd-be43b79fcabb7551677e2d27c75e2a500e2ba622.tar.bz2 |
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.
Diffstat (limited to 'rtemsbsd/include/machine/rtems-bsd-muteximpl.h')
-rw-r--r-- | rtemsbsd/include/machine/rtems-bsd-muteximpl.h | 220 |
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_ */ |