From 319813a59bc62e75025833d782c516f84b55e689 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 29 Feb 2012 15:23:06 +0100 Subject: [PATCH] Merge spin-lock implementations Separate spin-lock implementation from lock-implementation and put it into a non-public header, so it can be re-used by the DDE kit's and Fiasco.OC's capability-allocator spin lock. Fixes issue #123. --- base-foc/include/base/cap_sel_alloc.h | 71 +++++++++++++-------------- base-foc/lib/mk/env.mk | 9 ++-- base-foc/src/base/env/spin_lock.cc | 29 +++++++++++ base-foc/src/base/lock/lock_helper.h | 5 ++ base-foc/src/core/target.inc | 8 ++- base/src/base/lock/lock.cc | 39 +-------------- base/src/base/lock/spin_lock.h | 49 ++++++++++++++++++ os/include/dde_kit/spin_lock.h | 3 -- os/lib/mk/dde_kit.mk | 9 ++-- os/src/lib/dde_kit/spin_lock.cc | 13 ++--- 10 files changed, 140 insertions(+), 95 deletions(-) create mode 100644 base-foc/src/base/env/spin_lock.cc create mode 100644 base/src/base/lock/spin_lock.h diff --git a/base-foc/include/base/cap_sel_alloc.h b/base-foc/include/base/cap_sel_alloc.h index 396d2f830..12a9b6b4e 100644 --- a/base-foc/include/base/cap_sel_alloc.h +++ b/base-foc/include/base/cap_sel_alloc.h @@ -27,6 +27,7 @@ #include #include #include +#include #include /* Fiasco.OC includes */ @@ -80,42 +81,41 @@ namespace Genode Capability_allocator* cap_alloc(); + /** + * Low-level spin-lock to protect the allocator + * + * We cannot use a normal Genode lock because this lock is used by code + * executed prior the initialization of Genode. + */ + class Spin_lock + { + private: + + volatile int _spinlock; + + public: + + /** + * Constructor + */ + Spin_lock(); + + void lock(); + void unlock(); + + /** + * Lock guard + */ + typedef Genode::Lock_guard Guard; + }; + + + template class Capability_allocator_tpl : public Capability_allocator { private: - /** - * Low-level lock to protect the allocator - * - * We cannot use a normal Genode lock because this lock is used by code - * executed prior the initialization of Genode. - */ - class Alloc_lock - { - private: - - int _state; - - public: - - enum State { LOCKED, UNLOCKED }; - - /** - * Constructor - */ - Alloc_lock() : _state(UNLOCKED) {} - - void lock() - { - while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED)) - Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0)); - } - - void unlock() { _state = UNLOCKED; } - }; - - /** * Node in the capability cache, * associates global cap ids with kernel-capabilities. @@ -156,7 +156,7 @@ namespace Genode addr_t _cap_idx; /* start cap-selector */ Cap_node _data[SZ]; /* cache-nodes backing store */ Avl_tree _tree; /* cap cache */ - Alloc_lock _lock; + Spin_lock _lock; public: @@ -173,10 +173,10 @@ namespace Genode addr_t alloc(size_t num_caps) { - _lock.lock(); + Spin_lock::Guard guard(_lock); + int ret_base = _cap_idx; _cap_idx += num_caps * Fiasco::L4_CAP_SIZE; - _lock.unlock(); return ret_base; } @@ -208,7 +208,7 @@ namespace Genode void free(addr_t cap, size_t num_caps) { - _lock.lock(); + Spin_lock::Guard guard(_lock); for (unsigned i = 0; i < SZ; i++) if (!_data[i]._kcap == cap) { @@ -217,7 +217,6 @@ namespace Genode _data[i]._id = 0; break; } - _lock.unlock(); } }; } diff --git a/base-foc/lib/mk/env.mk b/base-foc/lib/mk/env.mk index 17ac5b253..733c424d0 100644 --- a/base-foc/lib/mk/env.mk +++ b/base-foc/lib/mk/env.mk @@ -1,7 +1,10 @@ -SRC_CC = env.cc context_area.cc cap_sel_alloc.cc reload_parent_cap.cc -LIBS = ipc heap log_console lock +SRC_CC = env.cc context_area.cc cap_sel_alloc.cc \ + reload_parent_cap.cc spin_lock.cc +LIBS = ipc heap log_console lock +INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock vpath env.cc $(BASE_DIR)/src/base/env vpath context_area.cc $(BASE_DIR)/src/base/env -vpath cap_sel_alloc.cc $(REP_DIR)/src/base/env +vpath cap_sel_alloc.cc $(REP_DIR)/src/base/env vpath reload_parent_cap.cc $(BASE_DIR)/src/base/env +vpath spin_lock.cc $(REP_DIR)/src/base/env diff --git a/base-foc/src/base/env/spin_lock.cc b/base-foc/src/base/env/spin_lock.cc new file mode 100644 index 000000000..00081157a --- /dev/null +++ b/base-foc/src/base/env/spin_lock.cc @@ -0,0 +1,29 @@ +/* + * \brief Spin-lock implementation for environment's capability -allocator. + * \author Stefan Kalkowski + * \date 2012-02-29 + * + * This is a Fiasco.OC-specific addition to the process enviroment. + */ + +/* + * Copyright (C) 2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include + +/* Lock implementation local include */ +#include + + +Genode::Spin_lock::Spin_lock() : _spinlock(SPINLOCK_UNLOCKED) {} + + +void Genode::Spin_lock::lock() { spinlock_lock(&_spinlock); } + + +void Genode::Spin_lock::unlock() { spinlock_unlock(&_spinlock); } diff --git a/base-foc/src/base/lock/lock_helper.h b/base-foc/src/base/lock/lock_helper.h index 03bc6747e..a293315a4 100644 --- a/base-foc/src/base/lock/lock_helper.h +++ b/base-foc/src/base/lock/lock_helper.h @@ -15,6 +15,9 @@ * under the terms of the GNU General Public License version 2. */ +#ifndef _INCLUDE__BASE__LOCK__LOCK_HELPER_H_ +#define _INCLUDE__BASE__LOCK__LOCK_HELPER_H_ + /* Genode includes */ #include #include @@ -106,3 +109,5 @@ static inline void thread_stop_myself() + Fiasco_capability::THREAD_IRQ_CAP; l4_irq_receive(irq, L4_IPC_NEVER); } + +#endif /* _INCLUDE__BASE__LOCK__LOCK_HELPER_H_ */ diff --git a/base-foc/src/core/target.inc b/base-foc/src/core/target.inc index eac9a047b..e448ca581 100644 --- a/base-foc/src/core/target.inc +++ b/base-foc/src/core/target.inc @@ -32,10 +32,13 @@ SRC_CC = main.cc \ context_area.cc \ cap_session_component.cc \ cpu_session_extension.cc \ - pd_session_extension.cc + pd_session_extension.cc \ + spin_lock.cc INC_DIR += $(REP_DIR)/src/core/include \ - $(GEN_CORE_DIR)/include + $(GEN_CORE_DIR)/include \ + $(REP_DIR)/src/base/lock \ + $(BASE_DIR)/src/base/lock vpath main.cc $(GEN_CORE_DIR) vpath multiboot_info.cc $(GEN_CORE_DIR) @@ -52,4 +55,5 @@ vpath dump_alloc.cc $(GEN_CORE_DIR) vpath context_area.cc $(GEN_CORE_DIR) vpath thread.cc $(REP_DIR)/src/base/thread vpath thread_bootstrap.cc $(REP_DIR)/src/base/thread +vpath spin_lock.cc $(REP_DIR)/src/base/env vpath %.cc $(REP_DIR)/src/core diff --git a/base/src/base/lock/lock.cc b/base/src/base/lock/lock.cc index 25233a872..91b8716ca 100644 --- a/base/src/base/lock/lock.cc +++ b/base/src/base/lock/lock.cc @@ -13,55 +13,18 @@ /* Genode includes */ #include -#include -#include /* local includes */ -#include +#include "spin_lock.h" using namespace Genode; - /** * Track interesting lock conditions, counters are only used for testing */ -int debug_spinlock_contention_cnt; int debug_lock_sleep_race_cnt; -/*************** - ** Utilities ** - ***************/ - -/* - * Spinlock functions used for protecting the critical sections within the - * 'lock' and 'unlock' functions. Contention in these short-running code - * portions is rare but is must be considered. - */ - -enum State { SPINLOCK_LOCKED, SPINLOCK_UNLOCKED }; - -static inline void spinlock_lock(volatile int *lock_variable) -{ - while (!cmpxchg(lock_variable, SPINLOCK_UNLOCKED, SPINLOCK_LOCKED)) { - - debug_spinlock_contention_cnt++; /* only for statistics */ - - /* - * Yield our remaining time slice to help the spinlock holder to pass - * the critical section. - */ - thread_yield(); - } -} - - -static inline void spinlock_unlock(volatile int *lock_variable) -{ - *lock_variable = SPINLOCK_UNLOCKED; -} - - /******************** ** Lock applicant ** ********************/ diff --git a/base/src/base/lock/spin_lock.h b/base/src/base/lock/spin_lock.h new file mode 100644 index 000000000..6b6dcba8d --- /dev/null +++ b/base/src/base/lock/spin_lock.h @@ -0,0 +1,49 @@ +/* + * \brief Spin lock implementation + * \author Norman Feske + * \author Stefan Kalkowski + * \date 2009-03-25 + */ + +/* + * Copyright (C) 2009-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__BASE__LOCK__SPIN_H_ +#define _INCLUDE__BASE__LOCK__SPIN_H_ + +/* Genode includes */ +#include + +/* local includes */ +#include + +/* + * Spinlock functions used for protecting the critical sections within the + * 'lock' and 'unlock' functions. Contention in these short-running code + * portions is rare but is must be considered. + */ + +enum State { SPINLOCK_LOCKED, SPINLOCK_UNLOCKED }; + +static inline void spinlock_lock(volatile int *lock_variable) +{ + while (!Genode::cmpxchg(lock_variable, SPINLOCK_UNLOCKED, SPINLOCK_LOCKED)) { + /* + * Yield our remaining time slice to help the spinlock holder to pass + * the critical section. + */ + thread_yield(); + } +} + + +static inline void spinlock_unlock(volatile int *lock_variable) +{ + *lock_variable = SPINLOCK_UNLOCKED; +} + +#endif /* _INCLUDE__BASE__LOCK__SPIN_H_ */ diff --git a/os/include/dde_kit/spin_lock.h b/os/include/dde_kit/spin_lock.h index 543f83a30..945c790d3 100644 --- a/os/include/dde_kit/spin_lock.h +++ b/os/include/dde_kit/spin_lock.h @@ -19,9 +19,6 @@ */ typedef volatile int dde_kit_spin_lock; -enum { DDE_KIT_SPIN_LOCK_LOCKED, DDE_KIT_SPIN_LOCK_UNLOCKED }; - - /** * Initialize spin lock * diff --git a/os/lib/mk/dde_kit.mk b/os/lib/mk/dde_kit.mk index 7e47c8806..94d8025c3 100644 --- a/os/lib/mk/dde_kit.mk +++ b/os/lib/mk/dde_kit.mk @@ -1,6 +1,7 @@ -SRC_C = lock.cc semaphore.cc panic.cc printf.cc interrupt.cc pgtab.cc \ - memory.cc thread.cc pci_tree.cc pci.cc resources.cc timer.cc \ - dde_kit.cc spin_lock.cc -LIBS = thread alarm +SRC_C = lock.cc semaphore.cc panic.cc printf.cc interrupt.cc pgtab.cc \ + memory.cc thread.cc pci_tree.cc pci.cc resources.cc timer.cc \ + dde_kit.cc spin_lock.cc +LIBS = thread alarm lock +REP_INC_DIR += src/base/lock vpath % $(REP_DIR)/src/lib/dde_kit diff --git a/os/src/lib/dde_kit/spin_lock.cc b/os/src/lib/dde_kit/spin_lock.cc index bbb052728..9488e6106 100644 --- a/os/src/lib/dde_kit/spin_lock.cc +++ b/os/src/lib/dde_kit/spin_lock.cc @@ -15,21 +15,16 @@ #include #include +#include + extern "C" { #include } -static inline void spinlock_lock(volatile int *lock_variable) -{ - while (!Genode::cmpxchg(lock_variable, DDE_KIT_SPIN_LOCK_UNLOCKED, - DDE_KIT_SPIN_LOCK_LOCKED)); -} - - extern "C" void dde_kit_spin_lock_init(dde_kit_spin_lock *spin_lock) { - *spin_lock = DDE_KIT_SPIN_LOCK_UNLOCKED; + *spin_lock = SPINLOCK_UNLOCKED; } @@ -52,6 +47,6 @@ extern "C" int dde_kit_spin_lock_try_lock(dde_kit_spin_lock *spin_lock) extern "C" void dde_kit_spin_lock_unlock(dde_kit_spin_lock *spin_lock) { - *spin_lock = DDE_KIT_SPIN_LOCK_UNLOCKED; + spinlock_unlock(spin_lock); }