mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
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.
This commit is contained in:
parent
72183f1536
commit
319813a59b
@ -27,6 +27,7 @@
|
||||
#include <util/avl_tree.h>
|
||||
#include <base/native_types.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/lock_guard.h>
|
||||
#include <cpu/atomic.h>
|
||||
|
||||
/* Fiasco.OC includes */
|
||||
@ -80,42 +81,41 @@ namespace Genode
|
||||
Capability_allocator* cap_alloc();
|
||||
|
||||
|
||||
template <unsigned SZ>
|
||||
class Capability_allocator_tpl : public Capability_allocator
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Low-level lock to protect the allocator
|
||||
* 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 Alloc_lock
|
||||
class Spin_lock
|
||||
{
|
||||
private:
|
||||
|
||||
int _state;
|
||||
volatile int _spinlock;
|
||||
|
||||
public:
|
||||
|
||||
enum State { LOCKED, UNLOCKED };
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Alloc_lock() : _state(UNLOCKED) {}
|
||||
Spin_lock();
|
||||
|
||||
void lock()
|
||||
{
|
||||
while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED))
|
||||
Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0));
|
||||
}
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
void unlock() { _state = UNLOCKED; }
|
||||
/**
|
||||
* Lock guard
|
||||
*/
|
||||
typedef Genode::Lock_guard<Spin_lock> Guard;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <unsigned SZ>
|
||||
class Capability_allocator_tpl : public Capability_allocator
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* 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<Cap_node> _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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
SRC_CC = env.cc context_area.cc cap_sel_alloc.cc reload_parent_cap.cc
|
||||
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 reload_parent_cap.cc $(BASE_DIR)/src/base/env
|
||||
vpath spin_lock.cc $(REP_DIR)/src/base/env
|
||||
|
29
base-foc/src/base/env/spin_lock.cc
vendored
Normal file
29
base-foc/src/base/env/spin_lock.cc
vendored
Normal file
@ -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 <base/cap_sel_alloc.h>
|
||||
|
||||
/* Lock implementation local include */
|
||||
#include <spin_lock.h>
|
||||
|
||||
|
||||
Genode::Spin_lock::Spin_lock() : _spinlock(SPINLOCK_UNLOCKED) {}
|
||||
|
||||
|
||||
void Genode::Spin_lock::lock() { spinlock_lock(&_spinlock); }
|
||||
|
||||
|
||||
void Genode::Spin_lock::unlock() { spinlock_unlock(&_spinlock); }
|
@ -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 <base/native_types.h>
|
||||
#include <base/thread.h>
|
||||
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -13,55 +13,18 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/cancelable_lock.h>
|
||||
#include <base/printf.h>
|
||||
#include <cpu/atomic.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lock_helper.h>
|
||||
#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 **
|
||||
********************/
|
||||
|
49
base/src/base/lock/spin_lock.h
Normal file
49
base/src/base/lock/spin_lock.h
Normal file
@ -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 <cpu/atomic.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lock_helper.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
LIBS = thread alarm lock
|
||||
REP_INC_DIR += src/base/lock
|
||||
|
||||
vpath % $(REP_DIR)/src/lib/dde_kit
|
||||
|
@ -15,21 +15,16 @@
|
||||
#include <cpu/atomic.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
#include <spin_lock.h>
|
||||
|
||||
extern "C" {
|
||||
#include <dde_kit/spin_lock.h>
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user