mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-14 08:16:28 +00:00
hw: re-implement kernel mutex
* Rename Kernel::Lock into Kernel::Mutex * Replace Guard object by template function that expects lambda to handle re-entrance by same cpu Ref genodelabs/genode#5425
This commit is contained in:
parent
c2cee1a885
commit
98032a2605
@ -7,7 +7,7 @@
|
||||
# add C++ sources
|
||||
SRC_CC += spec/arm/cortex_a15_cpu.cc
|
||||
SRC_CC += kernel/cpu_mp.cc
|
||||
SRC_CC += spec/arm/kernel/lock.cc
|
||||
SRC_CC += spec/arm/kernel/mutex.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(call select_from_repositories,lib/mk/spec/arm_v7/core-hw.inc)
|
||||
|
@ -9,7 +9,7 @@ SRC_CC += spec/arm/cortex_a9_board.cc
|
||||
SRC_CC += spec/arm/cortex_a9_cpu.cc
|
||||
SRC_CC += spec/arm/cortex_a9_global_timer.cc
|
||||
SRC_CC += spec/arm/gicv2.cc
|
||||
SRC_CC += spec/arm/kernel/lock.cc
|
||||
SRC_CC += spec/arm/kernel/mutex.cc
|
||||
SRC_CC += kernel/vm_thread_off.cc
|
||||
SRC_CC += kernel/cpu_mp.cc
|
||||
|
||||
|
@ -10,7 +10,7 @@ LIBS += syscall-hw
|
||||
# add C++ sources
|
||||
SRC_CC += kernel/cpu_mp.cc
|
||||
SRC_CC += spec/arm/generic_timer.cc
|
||||
SRC_CC += spec/arm/kernel/lock.cc
|
||||
SRC_CC += spec/arm/kernel/mutex.cc
|
||||
SRC_CC += spec/arm/kernel/thread_caches.cc
|
||||
SRC_CC += spec/arm/platform_support.cc
|
||||
SRC_CC += spec/arm_v8/cpu.cc
|
||||
|
@ -18,11 +18,11 @@ SRC_S += spec/x86_64/exception_vector.s
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += kernel/cpu_mp.cc
|
||||
SRC_CC += kernel/mutex.cc
|
||||
SRC_CC += kernel/vm_thread_on.cc
|
||||
SRC_CC += spec/x86_64/virtualization/kernel/vm.cc
|
||||
SRC_CC += spec/x86_64/virtualization/kernel/svm.cc
|
||||
SRC_CC += spec/x86_64/virtualization/kernel/vmx.cc
|
||||
SRC_CC += kernel/lock.cc
|
||||
SRC_CC += spec/x86_64/pic.cc
|
||||
SRC_CC += spec/x86_64/timer.cc
|
||||
SRC_CC += spec/x86_64/kernel/thread_exception.cc
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* \brief Kernel lock
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-11-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__SPEC__SMP__KERNEL__LOCK_H_
|
||||
#define _CORE__SPEC__SMP__KERNEL__LOCK_H_
|
||||
|
||||
namespace Kernel { class Lock; }
|
||||
|
||||
|
||||
class Kernel::Lock
|
||||
{
|
||||
private:
|
||||
|
||||
enum { INVALID = ~0U };
|
||||
|
||||
enum State { UNLOCKED, LOCKED };
|
||||
|
||||
int volatile _locked { UNLOCKED };
|
||||
unsigned volatile _current_cpu { INVALID };
|
||||
|
||||
public:
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
struct Guard
|
||||
{
|
||||
Lock &_lock;
|
||||
|
||||
explicit Guard(Lock &lock) : _lock(lock) { _lock.lock(); }
|
||||
|
||||
~Guard() { _lock.unlock(); }
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__SMP__KERNEL__LOCK_H_ */
|
@ -15,7 +15,7 @@
|
||||
/* core includes */
|
||||
#include <map_local.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/mutex.h>
|
||||
#include <kernel/main.h>
|
||||
#include <platform_pd.h>
|
||||
#include <platform_thread.h>
|
||||
@ -39,7 +39,7 @@ class Kernel::Main
|
||||
|
||||
static Main *_instance;
|
||||
|
||||
Lock _data_lock { };
|
||||
Mutex _mutex { };
|
||||
Cpu_pool _cpu_pool { };
|
||||
Irq::Pool _user_irq_pool { };
|
||||
Board::Address_space_id_allocator _addr_space_id_alloc { };
|
||||
@ -65,12 +65,14 @@ void Kernel::Main::_handle_kernel_entry()
|
||||
{
|
||||
Cpu::Context * context;
|
||||
|
||||
{
|
||||
Lock::Guard guard(_data_lock);
|
||||
|
||||
context =
|
||||
&_cpu_pool.cpu(Cpu::executing_id()).handle_exception_and_schedule();
|
||||
}
|
||||
_mutex.execute_exclusive(
|
||||
[&] () {
|
||||
Cpu &cpu = _cpu_pool.cpu(Cpu::executing_id());
|
||||
context = &cpu.handle_exception_and_schedule();
|
||||
},
|
||||
[&] () {
|
||||
Genode::error("Cpu ", Cpu::executing_id(), " re-entered lock.",
|
||||
"Kernel exception?!"); });
|
||||
|
||||
context->proceed();
|
||||
}
|
||||
@ -86,7 +88,7 @@ void Kernel::main_initialize_and_handle_kernel_entry()
|
||||
{
|
||||
using Boot_info = Hw::Boot_info<Board::Boot_info>;
|
||||
|
||||
static Lock init_lock;
|
||||
static Mutex init_mutex;
|
||||
static volatile unsigned nr_of_initialized_cpus { 0 };
|
||||
static volatile bool kernel_initialized { false };
|
||||
|
||||
@ -99,35 +101,34 @@ void Kernel::main_initialize_and_handle_kernel_entry()
|
||||
* Let the first CPU create a Main object and initialize the static
|
||||
* reference to it.
|
||||
*/
|
||||
{
|
||||
Lock::Guard guard(init_lock);
|
||||
|
||||
static Main instance;
|
||||
Main::_instance = &instance;
|
||||
|
||||
}
|
||||
init_mutex.execute_exclusive(
|
||||
[&] () {
|
||||
static Main instance;
|
||||
Main::_instance = &instance; },
|
||||
[&] () {
|
||||
Genode::error("recursive call of ", __func__); });
|
||||
|
||||
/* the CPU resumed if the kernel is already initialized */
|
||||
if (kernel_initialized) {
|
||||
|
||||
{
|
||||
Lock::Guard guard(Main::_instance->_data_lock);
|
||||
Main::_instance->_mutex.execute_exclusive(
|
||||
[&] () {
|
||||
if (nr_of_initialized_cpus == nr_of_cpus) {
|
||||
nr_of_initialized_cpus = 0;
|
||||
|
||||
if (nr_of_initialized_cpus == nr_of_cpus) {
|
||||
nr_of_initialized_cpus = 0;
|
||||
Main::_instance->_serial.init();
|
||||
Main::_instance->_global_irq_ctrl.init();
|
||||
}
|
||||
|
||||
Main::_instance->_serial.init();
|
||||
Main::_instance->_global_irq_ctrl.init();
|
||||
}
|
||||
nr_of_initialized_cpus = nr_of_initialized_cpus + 1;
|
||||
|
||||
nr_of_initialized_cpus = nr_of_initialized_cpus + 1;
|
||||
Main::_instance->_cpu_pool.cpu(Cpu::executing_id()).reinit_cpu();
|
||||
|
||||
Main::_instance->_cpu_pool.cpu(Cpu::executing_id()).reinit_cpu();
|
||||
|
||||
if (nr_of_initialized_cpus == nr_of_cpus) {
|
||||
Genode::raw("kernel resumed");
|
||||
}
|
||||
}
|
||||
if (nr_of_initialized_cpus == nr_of_cpus)
|
||||
Genode::raw("kernel resumed");
|
||||
},
|
||||
[&] () {
|
||||
Genode::error("recursive call of ", __func__); });
|
||||
|
||||
while (nr_of_initialized_cpus < nr_of_cpus) { }
|
||||
|
||||
@ -136,20 +137,21 @@ void Kernel::main_initialize_and_handle_kernel_entry()
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
/**
|
||||
* Let each CPU initialize its corresponding CPU object in the
|
||||
* CPU pool.
|
||||
*/
|
||||
Lock::Guard guard(Main::_instance->_data_lock);
|
||||
Main::_instance->_cpu_pool.initialize_executing_cpu(
|
||||
Main::_instance->_addr_space_id_alloc,
|
||||
Main::_instance->_user_irq_pool,
|
||||
Main::_instance->_core_platform_pd.kernel_pd(),
|
||||
Main::_instance->_global_irq_ctrl);
|
||||
Main::_instance->_mutex.execute_exclusive(
|
||||
[&] () {
|
||||
/**
|
||||
* Let each CPU initialize its corresponding CPU object in the
|
||||
* CPU pool.
|
||||
*/
|
||||
Main::_instance->_cpu_pool.initialize_executing_cpu(
|
||||
Main::_instance->_addr_space_id_alloc,
|
||||
Main::_instance->_user_irq_pool,
|
||||
Main::_instance->_core_platform_pd.kernel_pd(),
|
||||
Main::_instance->_global_irq_ctrl);
|
||||
|
||||
nr_of_initialized_cpus = nr_of_initialized_cpus + 1;
|
||||
};
|
||||
nr_of_initialized_cpus = nr_of_initialized_cpus + 1; },
|
||||
[&] () {
|
||||
Genode::error("recursive call of ", __func__); });
|
||||
|
||||
/**
|
||||
* Let all CPUs block until each CPU object in the CPU pool has been
|
||||
@ -161,29 +163,30 @@ void Kernel::main_initialize_and_handle_kernel_entry()
|
||||
* Let the primary CPU initialize the core main thread and finish
|
||||
* initialization of the boot info.
|
||||
*/
|
||||
{
|
||||
Lock::Guard guard(Main::_instance->_data_lock);
|
||||
Main::_instance->_mutex.execute_exclusive(
|
||||
[&] () {
|
||||
if (Cpu::executing_id() == Main::_instance->_cpu_pool.primary_cpu().id()) {
|
||||
Main::_instance->_cpu_pool.for_each_cpu([&] (Kernel::Cpu &cpu) {
|
||||
boot_info.kernel_irqs.add(cpu.timer().interrupt_id());
|
||||
});
|
||||
boot_info.kernel_irqs.add((unsigned)Board::Pic::IPI);
|
||||
|
||||
if (Cpu::executing_id() == Main::_instance->_cpu_pool.primary_cpu().id()) {
|
||||
Main::_instance->_cpu_pool.for_each_cpu([&] (Kernel::Cpu &cpu) {
|
||||
boot_info.kernel_irqs.add(cpu.timer().interrupt_id());
|
||||
});
|
||||
boot_info.kernel_irqs.add((unsigned)Board::Pic::IPI);
|
||||
Main::_instance->_core_main_thread.construct(
|
||||
Main::_instance->_addr_space_id_alloc,
|
||||
Main::_instance->_user_irq_pool,
|
||||
Main::_instance->_cpu_pool,
|
||||
Main::_instance->_core_platform_pd.kernel_pd());
|
||||
|
||||
Main::_instance->_core_main_thread.construct(
|
||||
Main::_instance->_addr_space_id_alloc,
|
||||
Main::_instance->_user_irq_pool,
|
||||
Main::_instance->_cpu_pool,
|
||||
Main::_instance->_core_platform_pd.kernel_pd());
|
||||
boot_info.core_main_thread_utcb =
|
||||
(addr_t)Main::_instance->_core_main_thread->utcb();
|
||||
|
||||
boot_info.core_main_thread_utcb =
|
||||
(addr_t)Main::_instance->_core_main_thread->utcb();
|
||||
|
||||
Genode::log("");
|
||||
Genode::log("kernel initialized");
|
||||
kernel_initialized = true;
|
||||
}
|
||||
}
|
||||
Genode::log("");
|
||||
Genode::log("kernel initialized");
|
||||
kernel_initialized = true;
|
||||
}
|
||||
},
|
||||
[&] () {
|
||||
Genode::error("recursive call of ", __func__); });
|
||||
|
||||
/**
|
||||
* Let secondary CPUs block until the primary CPU has initialized the
|
||||
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* \brief Kernel lock for multi-processor systems
|
||||
* \brief Kernel mutex
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2018-11-20
|
||||
* \date 2024-11-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Genode Labs GmbH
|
||||
* Copyright (C) 2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -17,25 +17,21 @@
|
||||
|
||||
/* base-hw core includes */
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/mutex.h>
|
||||
|
||||
|
||||
void Kernel::Lock::lock()
|
||||
bool Kernel::Mutex::_lock()
|
||||
{
|
||||
/* check for the lock holder being the same cpu */
|
||||
if (_current_cpu == Cpu::executing_id()) {
|
||||
/* at least print an error message */
|
||||
Genode::raw("Cpu ", _current_cpu,
|
||||
" error: re-entered lock. Kernel exception?!");
|
||||
}
|
||||
|
||||
while (!Genode::cmpxchg((volatile int*)&_locked, UNLOCKED, LOCKED)) { ; }
|
||||
while (!Genode::cmpxchg((volatile int*)&_locked, UNLOCKED, LOCKED))
|
||||
if (_current_cpu == Cpu::executing_id())
|
||||
return false;
|
||||
|
||||
_current_cpu = Cpu::executing_id();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Lock::unlock()
|
||||
void Kernel::Mutex::_unlock()
|
||||
{
|
||||
_current_cpu = INVALID;
|
||||
|
62
repos/base-hw/src/core/kernel/mutex.h
Normal file
62
repos/base-hw/src/core/kernel/mutex.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* \brief Kernel mutex
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2024-11-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__KERNEL__MUTEX_H_
|
||||
#define _CORE__KERNEL__MUTEX_H_
|
||||
|
||||
namespace Kernel { class Mutex; }
|
||||
|
||||
|
||||
class Kernel::Mutex
|
||||
{
|
||||
private:
|
||||
|
||||
enum { INVALID = ~0U };
|
||||
|
||||
enum State { UNLOCKED, LOCKED };
|
||||
|
||||
State volatile _locked { UNLOCKED };
|
||||
unsigned volatile _current_cpu { INVALID };
|
||||
|
||||
bool _lock();
|
||||
void _unlock();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Execute exclusively some critical section with lambda 'fn',
|
||||
* if the critical section is called recursively by the same cpu
|
||||
* lambda 'reentered' is called instead.
|
||||
*/
|
||||
void execute_exclusive(auto const &fn,
|
||||
auto const &reentered)
|
||||
{
|
||||
/*
|
||||
* If the lock cannot get acquired, it is already taken by this cpu.
|
||||
* That means implicitely that most probably some machine exception
|
||||
* during kernel execution forced the cpu to re-enter this critical
|
||||
* section.
|
||||
*/
|
||||
if (!_lock()) {
|
||||
reentered();
|
||||
|
||||
/* block forever */
|
||||
while (!_lock()) ;
|
||||
}
|
||||
|
||||
fn();
|
||||
_unlock();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__KERNEL__MUTEX_H_ */
|
@ -74,7 +74,7 @@ class Hw::Address_space : public Core::Address_space
|
||||
using Table = Hw::Page_table;
|
||||
using Array = Table::Allocator::Array<DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
Mutex _mutex { }; /* table lock */
|
||||
Genode::Mutex _mutex { }; /* table lock */
|
||||
Table &_tt; /* table virt addr */
|
||||
addr_t _tt_phys; /* table phys addr */
|
||||
Array *_tt_array = nullptr;
|
||||
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* \brief Kernel lock for multi-processor systems
|
||||
* \brief Kernel mutex
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2018-11-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Genode Labs GmbH
|
||||
* Copyright (C) 2019-2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -17,24 +17,21 @@
|
||||
|
||||
/* base-hw core includes */
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/mutex.h>
|
||||
|
||||
|
||||
void Kernel::Lock::lock()
|
||||
bool Kernel::Mutex::_lock()
|
||||
{
|
||||
/* check for the lock holder being the same cpu */
|
||||
if (_current_cpu == Cpu::executing_id()) {
|
||||
/* at least print an error message */
|
||||
Genode::raw("Cpu ", _current_cpu,
|
||||
" error: re-entered lock. Kernel exception?!");
|
||||
}
|
||||
if (_current_cpu == Cpu::executing_id())
|
||||
return false;
|
||||
|
||||
Cpu::wait_for_xchg(&_locked, LOCKED, UNLOCKED);
|
||||
Cpu::wait_for_xchg((volatile int*)&_locked, LOCKED, UNLOCKED);
|
||||
_current_cpu = Cpu::executing_id();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Lock::unlock()
|
||||
void Kernel::Mutex::_unlock()
|
||||
{
|
||||
_current_cpu = INVALID;
|
||||
|
Loading…
x
Reference in New Issue
Block a user