mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +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 <util/avl_tree.h>
|
||||||
#include <base/native_types.h>
|
#include <base/native_types.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
#include <base/lock_guard.h>
|
||||||
#include <cpu/atomic.h>
|
#include <cpu/atomic.h>
|
||||||
|
|
||||||
/* Fiasco.OC includes */
|
/* Fiasco.OC includes */
|
||||||
@ -80,42 +81,41 @@ namespace Genode
|
|||||||
Capability_allocator* cap_alloc();
|
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
|
* We cannot use a normal Genode lock because this lock is used by code
|
||||||
* executed prior the initialization of Genode.
|
* executed prior the initialization of Genode.
|
||||||
*/
|
*/
|
||||||
class Alloc_lock
|
class Spin_lock
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int _state;
|
volatile int _spinlock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum State { LOCKED, UNLOCKED };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Alloc_lock() : _state(UNLOCKED) {}
|
Spin_lock();
|
||||||
|
|
||||||
void lock()
|
void lock();
|
||||||
{
|
void unlock();
|
||||||
while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED))
|
|
||||||
Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
* Node in the capability cache,
|
||||||
* associates global cap ids with kernel-capabilities.
|
* associates global cap ids with kernel-capabilities.
|
||||||
@ -156,7 +156,7 @@ namespace Genode
|
|||||||
addr_t _cap_idx; /* start cap-selector */
|
addr_t _cap_idx; /* start cap-selector */
|
||||||
Cap_node _data[SZ]; /* cache-nodes backing store */
|
Cap_node _data[SZ]; /* cache-nodes backing store */
|
||||||
Avl_tree<Cap_node> _tree; /* cap cache */
|
Avl_tree<Cap_node> _tree; /* cap cache */
|
||||||
Alloc_lock _lock;
|
Spin_lock _lock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -173,10 +173,10 @@ namespace Genode
|
|||||||
|
|
||||||
addr_t alloc(size_t num_caps)
|
addr_t alloc(size_t num_caps)
|
||||||
{
|
{
|
||||||
_lock.lock();
|
Spin_lock::Guard guard(_lock);
|
||||||
|
|
||||||
int ret_base = _cap_idx;
|
int ret_base = _cap_idx;
|
||||||
_cap_idx += num_caps * Fiasco::L4_CAP_SIZE;
|
_cap_idx += num_caps * Fiasco::L4_CAP_SIZE;
|
||||||
_lock.unlock();
|
|
||||||
return ret_base;
|
return ret_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ namespace Genode
|
|||||||
|
|
||||||
void free(addr_t cap, size_t num_caps)
|
void free(addr_t cap, size_t num_caps)
|
||||||
{
|
{
|
||||||
_lock.lock();
|
Spin_lock::Guard guard(_lock);
|
||||||
|
|
||||||
for (unsigned i = 0; i < SZ; i++)
|
for (unsigned i = 0; i < SZ; i++)
|
||||||
if (!_data[i]._kcap == cap) {
|
if (!_data[i]._kcap == cap) {
|
||||||
@ -217,7 +217,6 @@ namespace Genode
|
|||||||
_data[i]._id = 0;
|
_data[i]._id = 0;
|
||||||
break;
|
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
|
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 env.cc $(BASE_DIR)/src/base/env
|
||||||
vpath context_area.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 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.
|
* 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 */
|
/* Genode includes */
|
||||||
#include <base/native_types.h>
|
#include <base/native_types.h>
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
@ -106,3 +109,5 @@ static inline void thread_stop_myself()
|
|||||||
+ Fiasco_capability::THREAD_IRQ_CAP;
|
+ Fiasco_capability::THREAD_IRQ_CAP;
|
||||||
l4_irq_receive(irq, L4_IPC_NEVER);
|
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 \
|
context_area.cc \
|
||||||
cap_session_component.cc \
|
cap_session_component.cc \
|
||||||
cpu_session_extension.cc \
|
cpu_session_extension.cc \
|
||||||
pd_session_extension.cc
|
pd_session_extension.cc \
|
||||||
|
spin_lock.cc
|
||||||
|
|
||||||
INC_DIR += $(REP_DIR)/src/core/include \
|
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 main.cc $(GEN_CORE_DIR)
|
||||||
vpath multiboot_info.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 context_area.cc $(GEN_CORE_DIR)
|
||||||
vpath thread.cc $(REP_DIR)/src/base/thread
|
vpath thread.cc $(REP_DIR)/src/base/thread
|
||||||
vpath thread_bootstrap.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
|
vpath %.cc $(REP_DIR)/src/core
|
||||||
|
@ -13,55 +13,18 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/cancelable_lock.h>
|
#include <base/cancelable_lock.h>
|
||||||
#include <base/printf.h>
|
|
||||||
#include <cpu/atomic.h>
|
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <lock_helper.h>
|
#include "spin_lock.h"
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track interesting lock conditions, counters are only used for testing
|
* Track interesting lock conditions, counters are only used for testing
|
||||||
*/
|
*/
|
||||||
int debug_spinlock_contention_cnt;
|
|
||||||
int debug_lock_sleep_race_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 **
|
** 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;
|
typedef volatile int dde_kit_spin_lock;
|
||||||
|
|
||||||
enum { DDE_KIT_SPIN_LOCK_LOCKED, DDE_KIT_SPIN_LOCK_UNLOCKED };
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize spin lock
|
* Initialize spin lock
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
SRC_C = lock.cc semaphore.cc panic.cc printf.cc interrupt.cc pgtab.cc \
|
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 \
|
memory.cc thread.cc pci_tree.cc pci.cc resources.cc timer.cc \
|
||||||
dde_kit.cc spin_lock.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
|
vpath % $(REP_DIR)/src/lib/dde_kit
|
||||||
|
@ -15,21 +15,16 @@
|
|||||||
#include <cpu/atomic.h>
|
#include <cpu/atomic.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
|
||||||
|
#include <spin_lock.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <dde_kit/spin_lock.h>
|
#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)
|
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)
|
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…
x
Reference in New Issue
Block a user