blob: 5c5963d6334da4aa339775c26c711f97e48f171a [file] [log] [blame]
//===--------------- JavaLocks.h - Fat lock management --------------------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef JAVA_LOCKS_H
#define JAVA_LOCKS_H
#include "mvm/Allocator.h"
#include "mvm/Threads/Locks.h"
namespace mvm {
class Thread;
}
namespace j3 {
class JavaObject;
class JavaThread;
class Jnjvm;
class JavaLock : public mvm::PermanentObject {
friend class JavaObject;
friend class LockSystem;
private:
mvm::LockRecursive internalLock;
mvm::SpinLock spinLock;
uint32_t waitingThreads;
uint32_t lockingThreads;
JavaThread* firstThread;
JavaObject* associatedObject;
uint32_t index;
JavaLock* nextFreeLock;
public:
JavaObject* getAssociatedObject() {
return associatedObject;
}
/// acquire - Acquires the internalLock.
///
bool acquire(JavaObject* obj) {
llvm_gcroot(obj, 0);
spinLock.lock();
lockingThreads++;
spinLock.unlock();
internalLock.lock();
spinLock.lock();
lockingThreads--;
spinLock.unlock();
if (associatedObject != obj) {
internalLock.unlock();
return false;
}
return true;
}
/// tryAcquire - Tries to acquire the lock.
///
int tryAcquire() {
return internalLock.tryLock();
}
/// acquireAll - Acquires the lock nb times.
void acquireAll(uint32 nb) {
internalLock.lockAll(nb);
}
/// release - Releases the internalLock.
///
void release(JavaObject* obj);
/// owner - Returns if the current thread owns this internalLock.
///
bool owner() {
return internalLock.selfOwner();
}
/// getOwner - Get the owner of this internalLock.
///
mvm::Thread* getOwner() {
return internalLock.getOwner();
}
/// JavaLock - Default constructor.
JavaLock(uint32_t i, JavaObject* a) {
llvm_gcroot(a, 0);
firstThread = 0;
index = i;
associatedObject = a;
waitingThreads = 0;
lockingThreads = 0;
}
static JavaLock* allocate(JavaObject*);
void deallocate();
uintptr_t getID();
static JavaLock* getFromID(uintptr_t val);
};
/// LockSystem - This class manages all Java locks used by the applications.
/// Each JVM must own an instance of this class and allocate Java locks
/// with it.
///
class LockSystem {
friend class JavaLock;
public:
// Fixed values. With these values, an index is on 18 bits.
static const uint32_t GlobalSize = 128;
static const uint32_t BitIndex = 11;
static const uint32_t IndexSize = 1 << BitIndex;
static const uint32_t BitMask = IndexSize - 1;
static const uint32_t MaxLocks = GlobalSize * IndexSize;
static const uint32_t BitGC = 2;
static const uint32_t BitHash = 10;
static const uint32_t BitGCHash = BitGC + BitHash;
/// LockTable - The global table that will hold the locks. The table is
/// a two-dimensional array, and only one entry is created, so that
/// the lock system does not eat up all memory on startup.
///
JavaLock* ** LockTable;
/// currentIndex - The current index in the tables. Always incremented,
/// never decremented.
///
uint32_t currentIndex;
/// freeLock - The list of locks that are allocated and available.
///
JavaLock* freeLock;
/// threadLock - Spin lock to protect the currentIndex field.
///
mvm::SpinLock threadLock;
/// associatedVM - The JVM associated with this lock system.
///
Jnjvm* associatedVM;
/// allocate - Allocate a JavaLock.
///
JavaLock* allocate(JavaObject* obj);
/// deallocate - Put a lock in the free list lock.
///
void deallocate(JavaLock* lock) {
lock->associatedObject = 0;
threadLock.lock();
lock->nextFreeLock = freeLock;
freeLock = lock;
threadLock.unlock();
}
/// LockSystem - Default constructor. Initialize the table.
///
LockSystem(Jnjvm* vm);
/// getLock - Get a lock from an index in the table.
///
JavaLock* getLock(uint32_t index) {
return LockTable[index >> BitIndex][index & BitMask];
}
};
}
#endif