[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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user