84 lines
1.4 KiB
C++
84 lines
1.4 KiB
C++
#ifndef _MTPRIM_HH_
|
|
#define _MTPRIM_HH_
|
|
|
|
#include "scheduler.hh"
|
|
#include "cortexa8.hh"
|
|
|
|
// Multithreading primitives (mutex, conditional)
|
|
|
|
// Mutex with support for recursive locking
|
|
// Uses Scheduler::Semaphore
|
|
class Mutex {
|
|
public:
|
|
Mutex() : owner_(nullptr), ownerCount_(0) {
|
|
}
|
|
|
|
~Mutex() {
|
|
assert(ownerCount_ == 0);
|
|
}
|
|
|
|
void lock() {
|
|
{
|
|
SemScopedAcquire lock_(semInt_);
|
|
if(owner_ == &global::scheduler->getCurrentThread()) {
|
|
++ownerCount_;
|
|
return;
|
|
}
|
|
}
|
|
semMutex_.acquire();
|
|
{
|
|
SemScopedAcquire lock_(semInt_);
|
|
assert(owner_ == nullptr);
|
|
owner_ = &global::scheduler->getCurrentThread();
|
|
ownerCount_ = 1;
|
|
}
|
|
}
|
|
|
|
void release() {
|
|
SemScopedAcquire lock_(semInt_);
|
|
assert(owner_ == &global::scheduler->getCurrentThread());
|
|
--ownerCount_;
|
|
if(ownerCount_ > 0) {
|
|
return;
|
|
}
|
|
owner_ = nullptr;
|
|
semMutex_.release();
|
|
}
|
|
|
|
private:
|
|
Scheduler::Semaphore semMutex_, semInt_;
|
|
Scheduler::Thread* owner_;
|
|
int ownerCount_;
|
|
};
|
|
|
|
template<class T>
|
|
class ScopedLock {
|
|
public:
|
|
ScopedLock(T& mutex) : mutex_(mutex), done_(false) {
|
|
mutex_.lock();
|
|
}
|
|
|
|
~ScopedLock() {
|
|
if(!done_)
|
|
mutex_.release();
|
|
}
|
|
|
|
void release() {
|
|
assert(!done_);
|
|
mutex_.release();
|
|
done_ = true;
|
|
}
|
|
|
|
void reacquire() {
|
|
assert(done_);
|
|
mutex_.lock();
|
|
done_ = false;
|
|
}
|
|
|
|
private:
|
|
T& mutex_;
|
|
bool done_;
|
|
};
|
|
|
|
#endif
|