[kernel][C++] add some simple C++ wrapper and RAII holders for various locks

Just a wrapper around mutex and spinlock for now.
This commit is contained in:
Travis Geiselbrecht
2021-11-10 22:34:11 -08:00
parent 98ca62d1e8
commit dbd1b6d903
4 changed files with 168 additions and 3 deletions

View File

@@ -52,3 +52,56 @@ static bool is_mutex_held(const mutex_t *m) {
}
__END_CDECLS
#ifdef __cplusplus
#include <lk/cpp.h>
// C++ wrapper object
class Mutex {
public:
constexpr Mutex() = default;
~Mutex() { mutex_destroy(&lock_); }
status_t acquire(lk_time_t timeout) { return mutex_acquire_timeout(&lock_, timeout); }
status_t release() { return mutex_release(&lock_); }
bool is_held() { return is_mutex_held(&lock_); }
// suppress default constructors
DISALLOW_COPY_ASSIGN_AND_MOVE(Mutex);
private:
mutex_t lock_ = MUTEX_INITIAL_VALUE(lock_);
// AutoLock has access to the inner lock
friend class AutoLock;
};
// RAII wrapper around the mutex
class AutoLock {
public:
explicit AutoLock(mutex_t *mutex) : mutex_(mutex) { mutex_acquire(mutex_); }
AutoLock(mutex_t &mutex) : AutoLock(&mutex) {}
explicit AutoLock(Mutex *mutex) : AutoLock(&mutex->lock_) {}
AutoLock(Mutex &mutex) : AutoLock(&mutex) {}
~AutoLock() { release(); }
// early release the mutex before the object goes out of scope
void release() {
if (likely(mutex_)) {
mutex_release(mutex_);
mutex_ = nullptr;
}
}
// suppress default constructors
DISALLOW_COPY_ASSIGN_AND_MOVE(AutoLock);
private:
mutex_t *mutex_ = nullptr;
};
#endif // __cplusplus

View File

@@ -69,3 +69,82 @@ static inline void spin_unlock_restore(
#define spin_unlock_irqrestore(lock, statep) spin_unlock_restore(lock, statep, SPIN_LOCK_FLAG_INTERRUPTS)
__END_CDECLS
#ifdef __cplusplus
#include <lk/cpp.h>
#include <assert.h>
// C++ wrapper around a C spinlock_t
class SpinLock {
public:
constexpr SpinLock() = default;
~SpinLock() { DEBUG_ASSERT(!is_held()); }
void lock() { spin_lock(&lock_); }
int trylock() { return spin_trylock(&lock_); }
void unlock() { spin_unlock(&lock_); }
bool is_held() { return spin_lock_held(&lock_); }
void lock_irqsave(spin_lock_saved_state_t *state) {
spin_lock_save(&lock_, state, SPIN_LOCK_FLAG_INTERRUPTS);
}
void unlock_irqrestore(spin_lock_saved_state_t state) {
spin_unlock_restore(&lock_, state, SPIN_LOCK_FLAG_INTERRUPTS);
}
// suppress default constructors
DISALLOW_COPY_ASSIGN_AND_MOVE(SpinLock);
private:
spin_lock_t lock_ = SPIN_LOCK_INITIAL_VALUE;
// friend classes to get to the inner lock
friend class AutoSpinLock;
friend class AutoSpinLockNoIrqSave;
};
// RAII wrappers for a spinlock, with and without IRQ Save
class AutoSpinLock {
public:
explicit AutoSpinLock(spin_lock_t *lock) : lock_(lock) { spin_lock_irqsave(lock_, state_); }
explicit AutoSpinLock(SpinLock *lock) : AutoSpinLock(&lock->lock_) {}
~AutoSpinLock() { release(); }
void release() {
if (likely(lock_)) {
spin_unlock_irqrestore(lock_, state_);
lock_ = nullptr;
}
}
// suppress default constructors
DISALLOW_COPY_ASSIGN_AND_MOVE(AutoSpinLock);
private:
spin_lock_t *lock_;
spin_lock_saved_state_t state_;
};
class AutoSpinLockNoIrqSave {
public:
explicit AutoSpinLockNoIrqSave(spin_lock_t *lock) : lock_(lock) { spin_lock(lock_); }
explicit AutoSpinLockNoIrqSave(SpinLock *lock) : AutoSpinLockNoIrqSave(&lock->lock_) {}
~AutoSpinLockNoIrqSave() { release(); }
void release() {
if (likely(lock_)) {
spin_unlock(lock_);
lock_ = nullptr;
}
}
// suppress default constructors
DISALLOW_COPY_ASSIGN_AND_MOVE(AutoSpinLockNoIrqSave);
private:
spin_lock_t *lock_;
};
#endif // __cplusplus

View File

@@ -7,11 +7,9 @@
*/
#pragma once
#include <arch/defines.h>
#include <arch/ops.h>
#include <arch/thread.h>
#include <lk/compiler.h>
#include <lk/list.h>
#include <stdbool.h>
#include <sys/types.h>
__BEGIN_CDECLS
@@ -63,6 +61,7 @@ int wait_queue_wake_all(wait_queue_t *, bool reschedule, status_t wait_queue_err
* remove the thread from whatever wait queue it's in.
* return an error if the thread is not currently blocked (or is the current thread)
*/
struct thread;
status_t thread_unblock_from_wait_queue(struct thread *t, status_t wait_queue_error);
__END_CDECLS

34
top/include/lk/cpp.h Normal file
View File

@@ -0,0 +1,34 @@
//
// Copyright (c) 2021 Travis Geiselbrecht
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
//
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
// Helper routines used in C++ code in LK
// Macro used to simplify the task of deleting all of the default copy
// constructors and assignment operators.
#define DISALLOW_COPY_ASSIGN_AND_MOVE(_class_name) \
_class_name(const _class_name&) = delete; \
_class_name(_class_name&&) = delete; \
_class_name& operator=(const _class_name&) = delete; \
_class_name& operator=(_class_name&&) = delete
// Macro used to simplify the task of deleting the non rvalue reference copy
// constructors and assignment operators. (IOW - forcing move semantics)
#define DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(_class_name) \
_class_name(const _class_name&) = delete; \
_class_name& operator=(const _class_name&) = delete
// Macro used to simplify the task of deleting the new and new[]
// operators. (IOW - disallow heap allocations)
#define DISALLOW_NEW \
static void* operator new(size_t) = delete; \
static void* operator new[](size_t) = delete