#include "ulInt.h"
#include "ulIntShared.h"
#include "hashTable.h"
-#include "random.h"
-#include "hostinfo.h"
static Bool mxInPanic = FALSE; // track when involved in a panic
}
-/*
- *-----------------------------------------------------------------------------
- *
- * MXUserSydrome --
- *
- * Generate the syndrome bits for this MXUser library.
- *
- * Each MXUser library has unique syndrome bits enabling the run time
- * detection of locks created with one copy of the MXUser library and
- * passed to another copy of the MXUser library.
- *
- * The syndrome bits are important as they prevent incompatible versions
- * of the MXUser library from trashing each other.
- *
- * The bits are generated by using a source of bits that is external to
- * a program and its libraries. This way no code or data based scheme
- * can be spoofed or aliased.
- *
- * Results:
- * As above
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-static uint32
-MXUserSyndrome(void)
-{
- uint32 syndrome;
- static Atomic_uint32 syndromeMem; // implicitly zero -- mbellon
-
- syndrome = Atomic_Read(&syndromeMem);
-
- if (syndrome == 0) {
- /*
- * Use the cryto quality source of bytes. This comes from the
- * host system. Should take somehow fail use the host's uptime
- */
-
- do {
- if (!Random_Crypto(sizeof(syndrome), &syndrome)) {
- syndrome = Hostinfo_SystemUpTime() & 0xFFFFFFFF;
- }
- } while (syndrome == 0); // syndrome bits must be non-zero
-
- /*
- * Attempt to update the syndrome value with the computed value using
- * a blind conditional write. One thread or another will have updated
- * the value.
- */
-
- Atomic_ReadIfEqualWrite(&syndromeMem, 0, syndrome);
- syndrome = Atomic_Read(&syndromeMem);
- }
-
- return syndrome;
-}
-
-
#if defined(MXUSER_DEBUG)
#define MXUSER_MAX_LOCKS_PER_THREAD (2 * MXUSER_MAX_REC_DEPTH)
static Atomic_Ptr hashTableMem;
-#if defined(_WIN32) && !defined(VMX86_VMX)
-static Atomic_Ptr hashLockMem;
-#endif
-
/*
*-----------------------------------------------------------------------------
HashTable *hash;
MXUserPerThread *perThread = NULL;
-#if defined(_WIN32) && !defined(VMX86_VMX)
- MXRecLock *hashLock = MXUserInternalSingleton(&hashLockMem);
-
- ASSERT(hashLock);
-
- hash = HashTable_AllocOnce(&hashTableMem, 1024, HASH_INT_KEY, NULL);
-
- MXRecLockAcquire(hashLock);
-#else
hash = HashTable_AllocOnce(&hashTableMem, 1024,
HASH_INT_KEY | HASH_FLAG_ATOMIC, NULL);
-#endif
if (!HashTable_Lookup(hash, tid, (void **) &perThread)) {
/* No entry for this tid was found, allocate one? */
}
}
-#if defined(_WIN32) && !defined(VMX86_VMX)
- MXRecLockRelease(hashLock);
-#endif
-
return perThread;
}
perThread->lockArray[lastEntry] = NULL; // tidy up memory
perThread->locksHeld--;
-
-#if defined(_WIN32) && !defined(VMX86_VMX)
- /*
- * On Windows thread IDs aren't greedily recycled. If a process creates and
- * destroys many threads this can cause a memory leak of perThread data
- * (and its overhead). We avoid this by atomically (via a lock) creating
- * (upon first lock acquired) and deleting (upon last lock release) a
- * perThread.
- *
- * Yes, this is a performance cost but it only affects Windows debug
- * builds and then not by very much - we tend to run for a long time
- * with either no locks held or at least one lock held.
- */
-
- if (perThread->locksHeld == 0) {
- HashTable *hash = Atomic_ReadPtr(&hashTableMem);
- MXRecLock *hashLock = MXUserInternalSingleton(&hashLockMem);
-
- ASSERT(hash);
- ASSERT(hashLock);
-
- MXRecLockAcquire(hashLock);
- HashTable_Delete(hash, tid);
- MXRecLockRelease(hashLock);
-
- free(perThread);
- }
-#endif
}
MXUserValidateSignature(MXUserHeader *header, // IN:
uint32 salt) // IN:
{
- uint32 syndrome = MXUserSyndrome();
-
- ASSERT(header);
-
- if ((header->signature[0] != syndrome) ||
- (header->signature[1] != salt)) {
- MXUserDumpAndPanic(header, "%s: expected (%X, %X) observed (%X, %X)\n",
- __FUNCTION__,
- syndrome, salt,
- header->signature[0],
- header->signature[1]);
+ if (header->signature != salt) {
+ MXUserDumpAndPanic(header, "%s: expected %X observed %X\n", __FUNCTION__,
+ salt, header->signature);
}
}
#endif
{
ASSERT(header);
- header->signature[0] = MXUserSyndrome();
- header->signature[1] = salt;
+#if defined(MXUSER_DEBUG)
+ header->signature = salt; // TODO: use salt + time: make runtime unique
+#else
+ header->signature = salt;
+#endif
}
void
MXUserClearSignature(MXUserHeader *header) // IN/OUT:
{
- ASSERT(header);
-
- header->signature[0] = 0;
- header->signature[1] = 0;
+ header->signature = 0;
}
Warning("%s: Barrier @ 0x%p\n", __FUNCTION__, barrier);
- Warning("\tsignature (0x%X, 0x%X)\n", barrier->header.signature[0],
- barrier->header.signature[1]);
+ Warning("\tsignature 0x%X\n", barrier->header.signature);
Warning("\tname %s\n", barrier->header.name);
Warning("\trank 0x%X\n", barrier->header.rank);
Warning("\tserial number %u\n", barrier->header.serialNumber);
__FUNCTION__);
}
- MXUserClearSignature(&barrier->header); // just in case...
-
MXUserRemoveFromList(&barrier->header);
MXUser_DestroyCondVar(barrier->contexts[0].condVar);
MXUser_DestroyCondVar(barrier->contexts[1].condVar);
MXUser_DestroyExclLock(barrier->lock);
+ MXUserClearSignature(&barrier->header); // just in case...
free(barrier->header.name);
barrier->header.name = NULL;
free(barrier);
Warning("%s: Exclusive lock @ 0x%p\n", __FUNCTION__, lock);
- Warning("\tsignature (0x%X, 0x%X)\n", lock->header.signature[0],
- lock->header.signature[1]);
+ Warning("\tsignature 0x%X\n", lock->header.signature);
Warning("\tname %s\n", lock->header.name);
Warning("\trank 0x%X\n", lock->header.rank);
Warning("\tserial number %u\n", lock->header.serialNumber);
- Warning("\tdepth count %u\n", MXRecLockCount(&lock->recursiveLock));
+ Warning("\tcount %u\n", lock->recursiveLock.referenceCount);
- Warning("\taddress of native owner data 0x%p\n",
+ Warning("\taddress of owner data 0x%p\n",
&lock->recursiveLock.nativeThreadID);
- Warning("\towner 0x%u\n", lock->recursiveLock.vmwThreadID);
-
if (stats && (stats->holder != NULL)) {
Warning("\tholder %p\n", stats->holder);
}
__FUNCTION__);
}
- MXUserClearSignature(&lock->header); // just in case...
-
MXRecLockDestroy(&lock->recursiveLock);
MXUserRemoveFromList(&lock->header);
free(stats);
}
+ MXUserClearSignature(&lock->header); // just in case...
free(lock->header.name);
lock->header.name = NULL;
free(lock);
pthread_mutex_t nativeLock; // Native lock object
#endif
- int depthCount; // Acquisition count
+ int referenceCount; // Acquisition count
MXUserThreadID nativeThreadID; // Native thread ID
- VThreadID vmwThreadID; // VMW thread ID
} MXRecLock;
MXRecLockSetNoOwner(MXRecLock *lock) // IN:
{
lock->nativeThreadID = MXUSER_INVALID_OWNER;
- lock->vmwThreadID = VTHREAD_INVALID_ID;
}
MXRecLockSetOwner(MXRecLock *lock) // IN/OUT:
{
lock->nativeThreadID = GetCurrentThreadId();
- lock->vmwThreadID = VThread_CurID();
}
{
/* a hack but it works portably */
memset((void *) &lock->nativeThreadID, 0xFF, sizeof(lock->nativeThreadID));
- lock->vmwThreadID = VTHREAD_INVALID_ID;
}
MXRecLockSetOwner(MXRecLock *lock) // IN:
{
lock->nativeThreadID = pthread_self();
- lock->vmwThreadID = VThread_CurID();
}
if (success) {
MXRecLockSetNoOwner(lock);
- lock->depthCount = 0;
+ lock->referenceCount = 0;
}
return success;
static INLINE uint32
MXRecLockCount(const MXRecLock *lock) // IN:
{
- return lock->depthCount;
+ return lock->referenceCount;
}
MXRecLockSetOwner(lock);
}
- lock->depthCount += count;
+ lock->referenceCount += count;
}
err);
}
- ASSERT(lock->depthCount == 0);
+ ASSERT(lock->referenceCount == 0);
}
MXRecLockIncCount(lock, 1);
MXRecLockDecCount(MXRecLock *lock, // IN/OUT:
uint32 count) // IN:
{
- ASSERT(count <= lock->depthCount);
- lock->depthCount -= count;
+ ASSERT(count <= lock->referenceCount);
+ lock->referenceCount -= count;
if (MXRecLockCount(lock) == 0) {
MXRecLockSetNoOwner(lock);
static INLINE void *
MXUserGetThreadID(void)
{
-#if defined(_WIN32)
- /*
- * On Windows there is a problem with using VThread_CurID() - it doesn't
- * maintain unique thread ID values (PR 780775). Native thread ID values
- * and special handling are used to resolve issues.
- */
-
- return (void *) (uintptr_t) GetCurrentThreadId(); // DWORD
-#else
- /*
- * Outside of Windows there are no known issues with using VThread_CurID
- * so that is what is used.
- */
-
return (void *) (uintptr_t) VThread_CurID(); // unsigned
-#endif
}
*/
typedef struct MXUserHeader {
- uint32 signature[2];
+ uint32 signature;
char *name;
+ MX_Rank rank;
+ uint32 serialNumber;
void (*dumpFunc)(struct MXUserHeader *);
void (*statsFunc)(struct MXUserHeader *);
ListItem item;
- uint32 serialNumber;
- MX_Rank rank;
} MXUserHeader;
Warning("%s: Read-write lock @ 0x%p\n", __FUNCTION__, lock);
- Warning("\tsignature (0x%X, 0x%X)\n", lock->header.signature[0],
- lock->header.signature[1]);
+ Warning("\tsignature 0x%X\n", lock->header.signature);
Warning("\tname %s\n", lock->header.name);
Warning("\trank 0x%X\n", lock->header.rank);
Warning("\tserial number %u\n", lock->header.serialNumber);
if (LIKELY(lock->useNative)) {
Warning("\tnativeLock 0x%p\n", &lock->nativeLock);
} else {
- Warning("\tdepth count %u\n", MXRecLockCount(&lock->recursiveLock));
+ Warning("\tcount %u\n", lock->recursiveLock.referenceCount);
}
Warning("\tholderCount %d\n", Atomic_Read(&lock->holderCount));
__FUNCTION__);
}
- MXUserClearSignature(&lock->header); // just in case...
-
if (LIKELY(lock->useNative)) {
int err = MXUserNativeRWDestroy(&lock->nativeLock);
}
HashTable_FreeUnsafe(lock->holderTable);
+ MXUserClearSignature(&lock->header); // just in case...
free(lock->header.name);
lock->header.name = NULL;
free(lock);
Warning("%s: Recursive lock @ 0x%p\n", __FUNCTION__, lock);
- Warning("\tsignature (0x%X, 0x%X)\n", lock->header.signature[0],
- lock->header.signature[1]);
+ Warning("\tsignature 0x%X\n", lock->header.signature);
Warning("\tname %s\n", lock->header.name);
Warning("\trank 0x%X\n", lock->header.rank);
Warning("\tserial number %u\n", lock->header.serialNumber);
-
Warning("\treference count %u\n", Atomic_Read(&lock->refCount));
if (lock->vmmLock == NULL) {
MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
- Warning("\tdepth count %u\n", MXRecLockCount(&lock->recursiveLock));
+ Warning("\tcount %u\n", lock->recursiveLock.referenceCount);
- Warning("\taddress of native owner data 0x%p\n",
+ Warning("\taddress of owner data 0x%p\n",
&lock->recursiveLock.nativeThreadID);
- Warning("\towner 0x%u\n", lock->recursiveLock.vmwThreadID);
-
if (stats && (stats->holder != NULL)) {
Warning("\tholder %p\n", stats->holder);
}
MXUserValidateSignature(&lock->header, MXUSER_REC_SIGNATURE);
if (Atomic_FetchAndDec(&lock->refCount) == 1) {
- MXUserClearSignature(&lock->header); // just in case...
-
if (lock->vmmLock == NULL) {
MXUserStats *stats;
}
}
+ MXUserClearSignature(&lock->header); // just in case...
free(lock->header.name);
lock->header.name = NULL;
free(lock);
Warning("%s: semaphore @ 0x%p\n", __FUNCTION__, sema);
- Warning("\tsignature (0x%X, 0x%X)\n", sema->header.signature[0],
- sema->header.signature[1]);
-
+ Warning("\tsignature 0x%X\n", sema->header.signature);
Warning("\tname %s\n", sema->header.name);
Warning("\trank 0x%X\n", sema->header.rank);
Warning("\tserial number %u\n", sema->header.serialNumber);
__FUNCTION__);
}
- MXUserClearSignature(&sema->header); // just in case...
-
err = MXUserDestroy(&sema->nativeSemaphore);
if (UNLIKELY(err != 0)) {
free(stats);
}
+ MXUserClearSignature(&sema->header); // just in case...
free(sema->header.name);
sema->header.name = NULL;
free(sema);