[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