blob: fecef719ca1db0eb65022808a57f60fbf6e5eb8f [file] [log] [blame]
//===------------------ Locks.h - Thread locks ----------------------------===//
//
// The Micro Virtual Machine
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef VMKIT_LOCKS_H
#define VMKIT_LOCKS_H
#include <pthread.h>
#include <cassert>
#include <cstdio>
#include "vmkit/Thread.h"
extern "C" void __llvm_gcroot(void**, void*) __attribute__((nothrow));
#define llvm_gcroot(a, b) __llvm_gcroot((void**)&a, b)
class gc;
namespace vmkit {
class Cond;
class FatLock;
class LockNormal;
class LockRecursive;
class Thread;
extern LockNormal lockForCtrl_C;
extern Cond condForCtrl_C;
extern bool finishForCtrl_C;
/// Lock - This class is an abstract class for declaring recursive and normal
/// locks.
///
class Lock {
friend class Cond;
private:
virtual void unsafeLock(int n) = 0;
virtual int unsafeUnlock() = 0;
protected:
/// owner - Which thread is currently holding the lock?
///
vmkit::Thread* owner;
/// internalLock - The lock implementation of the platform.
///
pthread_mutex_t internalLock;
public:
/// Lock - Creates a lock, recursive if rec is true.
///
Lock();
/// ~Lock - Give it a home.
///
virtual ~Lock();
/// lock - Acquire the lock.
///
virtual void lock() __attribute__ ((noinline)) = 0;
/// unlock - Release the lock.
///
virtual void unlock(vmkit::Thread* ownerThread = NULL) = 0;
/// selfOwner - Is the current thread holding the lock?
///
bool selfOwner(vmkit::Thread* ownerThread = NULL);
/// getOwner - Get the thread that is holding the lock.
///
vmkit::Thread* getOwner();
};
/// LockNormal - A non-recursive lock.
class LockNormal : public Lock {
friend class Cond;
private:
virtual void unsafeLock(int n) {
owner = vmkit::Thread::get();
}
virtual int unsafeUnlock() {
owner = 0;
return 0;
}
public:
LockNormal() : Lock() {}
virtual void lock() __attribute__ ((noinline));
virtual void unlock(vmkit::Thread* ownerThread = NULL);
int tryLock();
};
/// LockRecursive - A recursive lock.
class LockRecursive : public Lock {
friend class Cond;
private:
/// n - Number of times the lock has been locked.
///
int n;
virtual void unsafeLock(int a) {
n = a;
owner = vmkit::Thread::get();
}
virtual int unsafeUnlock() {
int ret = n;
n = 0;
owner = 0;
return ret;
}
public:
LockRecursive() : Lock() { n = 0; }
virtual void lock() __attribute__ ((noinline));
virtual void unlock(vmkit::Thread* ownerThread = NULL);
virtual int tryLock();
/// recursionCount - Get the number of times the lock has been locked.
///
int recursionCount() { return n; }
/// unlockAll - Unlock the lock, releasing it the number of times it is held.
/// Return the number of times the lock has been locked.
///
int unlockAll(vmkit::Thread* ownerThread = NULL);
/// lockAll - Acquire the lock count times.
///
void lockAll(int count) __attribute__ ((noinline));
};
/// SpinLock - This class implements a spin lock. A spin lock is OK to use
/// when it is held during short period of times. It is CPU expensive
/// otherwise.
class SpinLock {
public:
/// locked - Is the spin lock locked?
///
uint32 locked;
/// SpinLock - Initialize the lock as not being held.
///
SpinLock() { locked = 0; }
/// acquire - Acquire the spin lock, doing an active loop.
///
void acquire() {
for (uint32 count = 0; count < 1000; ++count) {
uint32 res = __sync_val_compare_and_swap(&locked, 0, 1);
if (!res) return;
}
while (__sync_val_compare_and_swap(&locked, 0, 1))
vmkit::Thread::yield();
}
void lock() { acquire(); }
/// release - Release the spin lock. This must be called by the thread
/// holding it.
///
void release() { locked = 0; }
void unlock(vmkit::Thread* ownerThread = NULL) { release(); }
};
class LockGuard
{
protected:
Lock& lock;
private: //Disabled constructors
LockGuard();
LockGuard(const LockGuard&);
public:
LockGuard(Lock& l) :
lock(l)
{
lock.lock();
}
virtual ~LockGuard()
{
lock.unlock();
}
};
} // end namespace vmkit
#endif // VMKIT_LOCKS_H