. lib/lock: minor performance optimizations, cleanups and other improvements.
. finish removal of lib/sync.
. Changes in shared code that don't affect open-vm-tools functionality.
Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
lib/slashProc/Makefile \
lib/string/Makefile \
lib/stubs/Makefile \
- lib/sync/Makefile \
lib/syncDriver/Makefile \
lib/system/Makefile \
lib/unicode/Makefile \
SUBDIRS += SLPv2Parser
SUBDIRS += string
SUBDIRS += stubs
-SUBDIRS += sync
SUBDIRS += syncDriver
SUBDIRS += system
SUBDIRS += unicode
* For a UserWorld, we want to get this cartel's proxy's cos pid.
*/
if (fileLockOptions.userWorld) {
- int pid = 0;
+ int pid, err;
- VMKernel_GetLockPid(&pid);
+ err = VMKernel_GetLockPid(&pid);
+ ASSERT_NOT_IMPLEMENTED(err == 0);
return pid;
}
+++ /dev/null
-/*********************************************************
- * Copyright (C) 1998 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *********************************************************/
-
-/*
- * syncMutex.h --
- *
- * Implements a platform independent mutex
- */
-
-#ifndef _SYNC_MUTEX_H_
-#define _SYNC_MUTEX_H_
-
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
-
-#if !defined(_WIN32)
-#if defined(N_PLAT_NLM)
-#include <nwerrno.h>
-#include <nwadv.h>
-#include <nwthread.h>
-#include <nwsemaph.h>
-#else
-#include <pthread.h>
-#endif
-#endif
-
-#include "syncWaitQ.h"
-#include "vm_atomic.h"
-
-/*
- * SyncMutex --
- */
-
-typedef struct SyncMutex {
-#if defined(N_PLAT_NLM)
- LONG semaphoreHandle;
-#else
- SyncWaitQ wq;
-
- /* Is the mutex unlocked? --hpreg */
- Atomic_uint32 unlocked;
-#if !defined(_WIN32)
- pthread_mutex_t _mutex;
-#endif
-#endif
-} SyncMutex;
-
-Bool SyncMutex_Init(SyncMutex *that,
- char const *path);
-void SyncMutex_Destroy(SyncMutex *that);
-Bool SyncMutex_Lock(SyncMutex *that);
-Bool SyncMutex_Unlock(SyncMutex *that);
-
-#if !defined(N_PLAT_NLM)
-Bool SyncMutex_Trylock(SyncMutex *that);
-#endif
-
-#endif // #ifndef _SYNC_MUTEX_H_
+++ /dev/null
-/*********************************************************
- * Copyright (C) 1998 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *********************************************************/
-
-/*
- * syncWaitQ.h --
- *
- * Implements a platform independent wait queue
- */
-
-#ifndef _SYNC_WAITQ_H_
-#define _SYNC_WAITQ_H_
-
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
-
-#if __APPLE__
-#include <pthread.h>
-#endif
-
-#include "vm_atomic.h"
-
-/*
- * syncWaitQ.h --
- *
- * The semantics of this wait queue primitive are as follows:
- *
- * o Client threads can add themselves to a waitqueue object and
- * receive a pollable handle via a call to SyncWaitQ_Add
- *
- * o When the waitqueue is woken up, each handle that was
- * previously obtained via a call to SyncWaitQ_Add becomes
- * signaled and remains so until it is removed via a call to
- * SyncWaitQ_Remove. Any calls to SyncWaitQ_Add, after the queue
- * has been woken up, will return fresh, unsignaled handles.
- *
- * For more information please refer to comments in the
- * respective syncWaitQ{host}.c files
- *
- * -- Ticho.
- *
- */
-
-/*
- * SyncWaitQ --
- *
- * Memory buffer that stores information about an wait queue
- * object.
- *
- * In the case of named queues, this structure can be allocated
- * on shared memory and shared between multiple processes.
- *
- * This structure, however, cannot be memcpy()-ed
- */
-
-
-typedef struct SyncWaitQ {
- /*
- * Common members used for both named and unnamed objects
- */
-
- // Whether the waitqueue has been initialized;
- Bool initialized;
-#ifndef _WIN32
- // Whether queue uses eventfd or pipe
- Bool usesEventFd;
-#endif
- // Whether there are any waiters on this queue
- Atomic_uint32 waiters;
- // A unique sequence number of the queue
- Atomic_uint64 seq;
-
- /*
- * Members used in case of named objects
- */
-
- // Name of the waitqueue object (FIFO path on Linux or Event name on Win32)
- char *pathName;
-
- /*
- * The following handles are only used only in the case of
- * anonymous pipes.
- *
- * On Win32 the readHandle is a handle to an event object
- *
- * On Posix the rwHandles are the read and write ends of an anonymous pipe,
- * or eventfd handle.
- *
- * -- Ticho
- */
-
-#ifdef _WIN32
- Atomic_uint64 readHandle;
-#else
- union {
- Atomic_uint64 pipeHandles64;
- Atomic_uint32 pipeHandles[2];
- Atomic_uint32 eventHandle;
- } u;
-# if __APPLE__
- pthread_mutex_t mutex;
-# endif
-#endif // #ifdef _WIN32
-} SyncWaitQ;
-
-Bool SyncWaitQ_Init(SyncWaitQ *that, char const *path);
-void SyncWaitQ_Destroy(SyncWaitQ *that);
-PollDevHandle SyncWaitQ_Add(SyncWaitQ *that);
-Bool SyncWaitQ_Remove(SyncWaitQ *that, PollDevHandle fd);
-Bool SyncWaitQ_WakeUp(SyncWaitQ *that);
-
-#endif // #infdef _SYNC_WAITQ_H_
MXUserThreadCurID = VThread_CurID;
}
+
/*
*-----------------------------------------------------------------------------
*
*/
void
-MXUserDumpAndPanic(MXRecLock *lock, // IN:
- const char *fmt, // IN:
- ...) // IN:
+MXUserDumpAndPanic(MXUserHeader *header, // IN:
+ const char *fmt, // IN:
+ ...) // IN:
{
char *msg;
va_list ap;
- Warning("%s: Lock @ %p\n", __FUNCTION__, lock);
- Warning("%s: signature %X\n", __FUNCTION__, lock->lockHeader.lockSignature);
- Warning("%s: count %u\n", __FUNCTION__, lock->lockHeader.lockCount);
- Warning("%s: name %s\n", __FUNCTION__, lock->lockHeader.lockName);
- Warning("%s: caller %p\n", __FUNCTION__, lock->lockHeader.lockCaller);
- Warning("%s: rank %d\n", __FUNCTION__, lock->lockHeader.lockRank);
-
- Warning("%s: VThreadID %d\n", __FUNCTION__,
- (int) lock->lockHeader.lockVThreadID);
+ (*header->lockDumper)(header);
va_start(ap, fmt);
msg = Str_SafeVasprintf(NULL, fmt, ap);
void
MXUser_AcquireExclLock(MXUserExclLock *lock) // IN/OUT:
{
- MXRecLockAcquire(&lock->basic, MXGetThreadID(), GetReturnAddress());
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
- if (MXRecLockCount(&lock->basic) > 1) {
- MXUserDumpAndPanic(&lock->basic,
+ MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress());
+
+ if (MXRecLockCount(&lock->lockRecursive) > 1) {
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: Acquire on an acquired exclusive lock",
__FUNCTION__);
}
*
* MXUser_AcquireRecLock --
*
- * An acquisition is made (lock is taken) on the specified recursive
- * lock.
+ * An acquisition is made (lock is taken) on the specified recursive lock.
*
* Only the owner (thread) of a recursive lock may recurse on it.
*
void
MXUser_AcquireRecLock(MXUserRecLock *lock) // IN/OUT:
{
- MXRecLockAcquire(&lock->basic, MXGetThreadID(), GetReturnAddress());
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress());
}
#include "ulInt.h"
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserDumpExclLock
+ *
+ * Dump an exclusive lock.
+ *
+ * Results:
+ * A dump.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+MXUserDumpExclLock(MXUserHeader *header) // IN:
+{
+ MXUserExclLock *lock = (MXUserExclLock *) header;
+
+ Warning("%s: Exclusive lock @ %p\n", __FUNCTION__, lock);
+
+ Warning("\tsignature %X\n", lock->lockHeader.lockSignature);
+ Warning("\tname %s\n", lock->lockHeader.lockName);
+ Warning("\trank %d\n", lock->lockHeader.lockRank);
+
+ Warning("\tcount %u\n", lock->lockRecursive.lockCount);
+
+#if defined(VMX86_DEBUG)
+ Warning("\tcaller %p\n", lock->lockRecursive.lockCaller);
+ Warning("\tVThreadID %d\n", (int) lock->lockRecursive.lockVThreadID);
+#endif
+}
+
+
/*
*-----------------------------------------------------------------------------
*
properName = Util_SafeStrdup(userName);
}
- if (!MXRecLockInit(&lock->basic, properName, rank)) {
+ lock->lockHeader.lockName = properName;
+ lock->lockHeader.lockSignature = USERLOCK_SIGNATURE;
+ lock->lockHeader.lockRank = rank;
+ lock->lockHeader.lockDumper = MXUserDumpExclLock;
+
+ if (!MXRecLockInit(&lock->lockRecursive)) {
free(lock);
free(properName);
lock = NULL;
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserDumpRecLock
+ *
+ * Dump an recursive lock.
+ *
+ * Results:
+ * A dump.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+MXUserDumpRecLock(MXUserHeader *header) // IN:
+{
+ MXUserRecLock *lock = (MXUserRecLock *) header;
+
+ Warning("%s: Recursive lock @ %p\n", __FUNCTION__, lock);
+
+ Warning("\tsignature %X\n", lock->lockHeader.lockSignature);
+ Warning("\tname %s\n", lock->lockHeader.lockName);
+ Warning("\trank %d\n", lock->lockHeader.lockRank);
+
+ Warning("\tcount %u\n", lock->lockRecursive.lockCount);
+
+#if defined(VMX86_DEBUG)
+ Warning("\tcaller %p\n", lock->lockRecursive.lockCaller);
+ Warning("\tVThreadID %d\n", (int) lock->lockRecursive.lockVThreadID);
+#endif
+
+ Warning("\tlockVmm %p\n", lock->lockVmm);
+}
+
+
/*
*-----------------------------------------------------------------------------
*
properName = Util_SafeStrdup(userName);
}
- if (MXRecLockInit(&lock->basic, properName, rank)) {
- lock->vmmLock = NULL;
+ lock->lockHeader.lockName = properName;
+ lock->lockHeader.lockSignature = USERLOCK_SIGNATURE;
+ lock->lockHeader.lockRank = rank;
+ lock->lockHeader.lockDumper = MXUserDumpRecLock;
+
+ if (MXRecLockInit(&lock->lockRecursive)) {
+ lock->lockVmm = NULL;
} else {
free(lock);
free(properName);
MXUser_DestroyExclLock(MXUserExclLock *lock) // IN:
{
if (lock != NULL) {
- if (MXRecLockCount(&lock->basic) > 0) {
- MXUserDumpAndPanic(&lock->basic,
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ if (MXRecLockCount(&lock->lockRecursive) > 0) {
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: Destroy of an acquired exclusive lock",
__FUNCTION__);
}
- MXRecLockDestroy(&lock->basic);
+ MXRecLockDestroy(&lock->lockRecursive);
+ free((void *) lock->lockHeader.lockName);
free(lock);
}
}
MXUser_DestroyRecLock(MXUserRecLock *lock) // IN:
{
if (lock != NULL) {
- if (MXRecLockCount(&lock->basic) > 0) {
- MXUserDumpAndPanic(&lock->basic,
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ if (MXRecLockCount(&lock->lockRecursive) > 0) {
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: Destroy of an acquired recursive lock",
__FUNCTION__);
}
- MXRecLockDestroy(&lock->basic);
+ MXRecLockDestroy(&lock->lockRecursive);
+ free((void *) lock->lockHeader.lockName);
free(lock);
}
}
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#if defined(_WIN32)
typedef DWORD MXThreadID;
+#define MXUSER_INVALID_OWNER 0xFFFFFFFF
#else
#include <pthread.h>
#include <errno.h>
void MXUserIDHack(void);
EXTERN VThreadID (*MXUserThreadCurID)(void);
-/*
- * MXUser lock header - all MXUser locks start with this
- */
-
-#define USERLOCK_SIGNATURE 0x75677976 // 'LOCK' in memory
-
-typedef struct {
- const char *lockName;
- uint32 lockSignature;
- int lockCount; // May be Atomic someday (read-write locks?)
- MXThreadID lockOwner; // Native thread ID
- MX_Rank lockRank;
- VThreadID lockVThreadID;
-
- /*
- * Statistics data
- *
- * The fancy statistics that we will keep on each lock will live here too,
- * attached via a pointer.
- */
-
- const void *lockCaller; // return address of lock acquisition routine
-} MXUserHeader;
-
/*
* A portable recursive lock.
- *
- * The MXUser simple and recursive locks are built on top of this.
*/
#define MXUSER_MAX_REC_DEPTH 16
typedef struct {
- MXUserHeader lockHeader;
-
#if defined(_WIN32)
- CRITICAL_SECTION lockObject;
+ CRITICAL_SECTION lockObject; // Native lock object
#else
- pthread_mutex_t lockObject;
+ pthread_mutex_t lockObject; // Native lock object
+#endif
+
+ int lockCount; // Acquisition count
+ MXThreadID lockOwner; // Native thread ID
+
+#if defined(VMX86_DEBUG)
+ VThreadID lockVThreadID; // VThreadID, when available
+ const void *lockCaller; // return address of acquisition routine
#endif
} MXRecLock;
* - exclusive (non-recursive) locks catch the recursion and panic
* rather than deadlock.
*
- * There are 7 environment specific primitives:
+ * There are 6 environment specific primitives:
*
- * MXGetThreadID (thread identification)
- * MXRecLockIsOwner (is lock owned by caller?)
- * MXRecLockObjectInit (initialize)
- * MXRecLockDestroy (dispose after use)
- * MXRecLockAcquire (lock)
- * MXRecLockTryAcquire (conditional lock)
- * MXRecLockRelease (unlock)
+ * MXRecLockObjectInit initialize native lock before use
+ * MXRecLockDestroy destroy lock after use
+ * MXRecLockIsOwner is lock owned by caller?
+ * MXRecLockAcquire lock
+ * MXRecLockTryAcquire conditional lock
+ * MXRecLockRelease unlock
*
* Windows has a native recursive lock, the CRITICAL_SECTION. POSIXen,
* unfortunately, do not ensure access to such a facility. The recursive
*/
#if defined(_WIN32)
-static INLINE MXThreadID
-MXGetThreadID(void)
-{
- return GetCurrentThreadId();
-}
-
-
-static INLINE Bool
-MXRecLockIsOwner(const MXRecLock *lock) // IN:
-{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
- return lock->lockHeader.lockOwner == MXGetThreadID();
-}
-
-
static INLINE Bool
MXRecLockObjectInit(CRITICAL_SECTION *lockObject) // IN/OUT:
{
static INLINE void
MXRecLockDestroy(MXRecLock *lock) // IN/OUT:
{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
DeleteCriticalSection(&lock->lockObject);
- free((void *) lock->lockHeader.lockName);
+}
+
+
+static INLINE Bool
+MXRecLockIsOwner(const MXRecLock *lock) // IN:
+{
+ return lock->lockOwner == GetCurrentThreadId();
}
static INLINE void
MXRecLockAcquire(MXRecLock *lock, // IN/OUT:
- MXThreadID self, // IN:
const void *location) // IN:
{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
EnterCriticalSection(&lock->lockObject);
- ASSERT((lock->lockHeader.lockCount >= 0) &&
- (lock->lockHeader.lockCount < MXUSER_MAX_REC_DEPTH));
+ ASSERT((lock->lockCount >= 0) && (lock->lockCount < MXUSER_MAX_REC_DEPTH));
- if (lock->lockHeader.lockCount == 0) {
- ASSERT(lock->lockHeader.lockVThreadID == VTHREAD_INVALID_ID);
- lock->lockHeader.lockOwner = self;
- lock->lockHeader.lockCaller = location;
- lock->lockHeader.lockVThreadID = (*MXUserThreadCurID)();
+ if (lock->lockCount == 0) {
+ ASSERT(lock->lockOwner == MXUSER_INVALID_OWNER);
+ lock->lockOwner = GetCurrentThreadId();
+#if defined(VMX86_DEBUG)
+ lock->lockCaller = location;
+ lock->lockVThreadID = (*MXUserThreadCurID)();
+#endif
}
- lock->lockHeader.lockCount++;
+ lock->lockCount++;
}
static INLINE Bool
MXRecLockTryAcquire(MXRecLock *lock, // IN/OUT:
- MXThreadID self, // IN:
const void *location) // IN:
{
Bool success;
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
success = TryEnterCriticalSection(&lock->lockObject);
if (success) {
- ASSERT((lock->lockHeader.lockCount >= 0) &&
- (lock->lockHeader.lockCount < MXUSER_MAX_REC_DEPTH));
-
- if (lock->lockHeader.lockCount == 0) {
- ASSERT(lock->lockHeader.lockVThreadID == VTHREAD_INVALID_ID);
- lock->lockHeader.lockOwner = self;
- lock->lockHeader.lockCaller = location;
- lock->lockHeader.lockVThreadID = (*MXUserThreadCurID)();
+ ASSERT((lock->lockCount >= 0) &&
+ (lock->lockCount < MXUSER_MAX_REC_DEPTH));
+
+ if (lock->lockCount == 0) {
+ ASSERT(lock->lockOwner == MXUSER_INVALID_OWNER);
+ lock->lockOwner = GetCurrentThreadId();
+
+#if defined(VMX86_DEBUG)
+ lock->lockCaller = location;
+ lock->lockVThreadID = (*MXUserThreadCurID)();
+#endif
}
- lock->lockHeader.lockCount++;
+ lock->lockCount++;
}
return success;
static INLINE void
MXRecLockRelease(MXRecLock *lock) // IN/OUT:
{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+ ASSERT((lock->lockCount > 0) && (lock->lockCount < MXUSER_MAX_REC_DEPTH));
- ASSERT((lock->lockHeader.lockCount > 0) &&
- (lock->lockHeader.lockCount < MXUSER_MAX_REC_DEPTH));
+ lock->lockCount--;
- lock->lockHeader.lockCount--;
+ if (lock->lockCount == 0) {
+ lock->lockOwner = MXUSER_INVALID_OWNER;
- if (lock->lockHeader.lockCount == 0) {
- lock->lockHeader.lockCaller = NULL;
- lock->lockHeader.lockVThreadID = VTHREAD_INVALID_ID;
+#if defined(VMX86_DEBUG)
+ lock->lockCaller = NULL;
+ lock->lockVThreadID = VTHREAD_INVALID_ID;
+#endif
}
LeaveCriticalSection(&lock->lockObject);
}
#else
-static INLINE MXThreadID
-MXGetThreadID(void)
-{
- return pthread_self();
-}
-
-
-static INLINE Bool
-MXRecLockIsOwner(const MXRecLock *lock) // IN:
-{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
- return pthread_equal(lock->lockHeader.lockOwner, pthread_self());
-}
-
-
static INLINE Bool
MXRecLockObjectInit(pthread_mutex_t *lockObject) // IN/OUT:
{
{
int err;
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
err = pthread_mutex_destroy(&lock->lockObject);
if (vmx86_debug && (err != 0)) {
Panic("%s: pthread_mutex_destroy returned %d\n", __FUNCTION__, err);
}
+}
+
- free((void *) lock->lockHeader.lockName);
+static INLINE Bool
+MXRecLockIsOwner(const MXRecLock *lock) // IN:
+{
+ return pthread_equal(lock->lockOwner, pthread_self());
}
static INLINE void
MXRecLockAcquire(MXRecLock *lock, // IN/OUT:
- MXThreadID self, // IN:
void *location) // IN:
{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
- if ((lock->lockHeader.lockCount != 0) &&
- pthread_equal(lock->lockHeader.lockOwner, pthread_self())) {
- ASSERT((lock->lockHeader.lockCount > 0) &&
- (lock->lockHeader.lockCount < MXUSER_MAX_REC_DEPTH));
+ if ((lock->lockCount != 0) &&
+ pthread_equal(lock->lockOwner, pthread_self())) {
+ ASSERT((lock->lockCount > 0) &&
+ (lock->lockCount < MXUSER_MAX_REC_DEPTH));
- lock->lockHeader.lockCount++;
+ lock->lockCount++;
} else {
int err;
Panic("%s: pthread_mutex_lock returned %d\n", __FUNCTION__, err);
}
- ASSERT(lock->lockHeader.lockCount == 0);
- ASSERT(lock->lockHeader.lockVThreadID == VTHREAD_INVALID_ID);
+ ASSERT(lock->lockCount == 0);
+ ASSERT(lock->lockVThreadID == VTHREAD_INVALID_ID);
- lock->lockHeader.lockOwner = self;
- lock->lockHeader.lockCaller = location;
- lock->lockHeader.lockCount = 1;
- lock->lockHeader.lockVThreadID = (*MXUserThreadCurID)();
+ lock->lockOwner = pthread_self();
+ lock->lockCount = 1;
+
+#if defined(VMX86_DEBUG)
+ lock->lockCaller = location;
+ lock->lockVThreadID = (*MXUserThreadCurID)();
+#endif
}
}
static INLINE Bool
MXRecLockTryAcquire(MXRecLock *lock, // IN/OUT:
- MXThreadID self, // IN:
void *location) // IN:
{
int err;
Bool acquired;
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
err = pthread_mutex_trylock(&lock->lockObject);
if (err == 0) {
- ASSERT((lock->lockHeader.lockCount >= 0) &&
- (lock->lockHeader.lockCount < MXUSER_MAX_REC_DEPTH));
-
- if (lock->lockHeader.lockCount == 0) {
- ASSERT(lock->lockHeader.lockVThreadID == VTHREAD_INVALID_ID);
- lock->lockHeader.lockOwner = self;
- lock->lockHeader.lockCaller = location;
- lock->lockHeader.lockVThreadID = (*MXUserThreadCurID)();
+ ASSERT((lock->lockCount >= 0) &&
+ (lock->lockCount < MXUSER_MAX_REC_DEPTH));
+
+ if (lock->lockCount == 0) {
+ ASSERT(lock->lockVThreadID == VTHREAD_INVALID_ID);
+ lock->lockOwner = pthread_self();
+
+#if defined(VMX86_DEBUG)
+ lock->lockCaller = location;
+ lock->lockVThreadID = (*MXUserThreadCurID)();
+#endif
}
- lock->lockHeader.lockCount++;
+ lock->lockCount++;
acquired = TRUE;
} else {
static INLINE void
MXRecLockRelease(MXRecLock *lock) // IN/OUT:
{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
- ASSERT((lock->lockHeader.lockCount > 0) &&
- (lock->lockHeader.lockCount < MXUSER_MAX_REC_DEPTH));
+ ASSERT((lock->lockCount > 0) && (lock->lockCount < MXUSER_MAX_REC_DEPTH));
- lock->lockHeader.lockCount--;
+ lock->lockCount--;
- if (lock->lockHeader.lockCount == 0) {
+ if (lock->lockCount == 0) {
int err;
- lock->lockHeader.lockCaller = NULL;
- lock->lockHeader.lockVThreadID = VTHREAD_INVALID_ID;
+ /* a hack but it works portably */
+ memset((void *) &lock->lockOwner, 0xFF, sizeof(lock->lockOwner));
+
+#if defined(VMX86_DEBUG)
+ lock->lockCaller = NULL;
+ lock->lockVThreadID = VTHREAD_INVALID_ID;
+#endif
err = pthread_mutex_unlock(&lock->lockObject);
#endif
-static INLINE void
-MXRecLockInitHeader(MXRecLock *lock, // IN/OUT:
- const char *userName, // IN:
- MX_Rank rank) // IN:
-{
- lock->lockHeader.lockName = userName;
- lock->lockHeader.lockSignature = USERLOCK_SIGNATURE;
- lock->lockHeader.lockCount = 0;
- lock->lockHeader.lockRank = rank;
- lock->lockHeader.lockVThreadID = VTHREAD_INVALID_ID;
- lock->lockHeader.lockCaller = NULL;
-}
-
-
/*
* Initialization of portable recursive lock.
*/
static INLINE Bool
-MXRecLockInit(MXRecLock *lock, // IN/OUT:
- const char *userName, // IN:
- MX_Rank rank) // IN:
+MXRecLockInit(MXRecLock *lock) // IN/OUT:
{
- ASSERT(rank == RANK_UNRANKED); // NOT FOR LONG
- ASSERT(userName != NULL);
-
if (!MXRecLockObjectInit(&lock->lockObject)) {
return FALSE;
}
- MXRecLockInitHeader(lock, userName, rank);
+#if defined(_WIN32)
+ lock->lockOwner = MXUSER_INVALID_OWNER;
+#else
+ /* a hack but it works portably */
+ memset((void *) &lock->lockOwner, 0xFF, sizeof(lock->lockOwner));
+#endif
+
+ lock->lockCount = 0;
+
+#if defined(VMX86_DEBUG)
+ lock->lockVThreadID = VTHREAD_INVALID_ID;
+ lock->lockCaller = NULL;
+#endif
return TRUE;
}
static INLINE uint32
MXRecLockCount(const MXRecLock *lock) // IN:
{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
- return lock->lockHeader.lockCount;
+ return lock->lockCount;
}
-static INLINE const char *
-MXRecLockName(const MXRecLock *lock) // IN:
-{
- ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
-
- return lock->lockHeader.lockName;
-}
+/*
+ * MXUser lock header - all MXUser locks start with this
+ */
+#define USERLOCK_SIGNATURE 0x75677976 // 'LOCK' in memory
-static INLINE uint32
-MXRecLockSignature(const MXRecLock *lock) // IN:
-{
- return lock->lockHeader.lockSignature;
-}
+typedef struct MXUserHeader {
+ uint32 lockSignature;
+ MX_Rank lockRank;
+ const char *lockName;
+ void (*lockDumper)(struct MXUserHeader *);
+ /* THIS SPACE FOR RENT (STATISTICS POINTER) */
+} MXUserHeader;
/*
* The internal lock types
struct MXUserExclLock
{
- MXRecLock basic;
+ MXUserHeader lockHeader;
+
+ MXRecLock lockRecursive;
};
struct MXUserRecLock
{
- MXRecLock basic;
+ MXUserHeader lockHeader;
+
+ MXRecLock lockRecursive;
/*
* This is the MX recursive lock override pointer. This pointer is NULL
* !NULL use pointed to MX recursive lock
*/
- void *vmmLock;
+ void *lockVmm;
};
struct MXUserRWLock
{
- MXRecLock lockRecursive; // Used as a header or maybe for real
-
- uint8 lockTaken[VTHREAD_MAX_THREADS];
+ MXUserHeader lockHeader;
#if defined(_WIN32)
+ MXRecLock lockRecursive;
SRWLOCK lockReadWrite;
#else
#if defined(PTHREAD_RWLOCK_INITIALIZER)
- pthread_rwlock_t lockObject;
+ pthread_rwlock_t lockReadWrite;
+#else
+ MXRecLock lockRecursive;
#endif
#endif
+
+ uint8 lockTaken[VTHREAD_MAX_THREADS];
};
/*
Bool MXUserIsAllUnlocked(const MXUserRWLock *lock);
-void MXUserDumpAndPanic(MXRecLock *lock,
+void MXUserDumpAndPanic(MXUserHeader *header,
const char *fmt,
...);
#endif
Bool
MXUser_IsLockedByCurThreadExclLock(const MXUserExclLock *lock) // IN:
{
- return MXRecLockIsOwner(&lock->basic);
+ return MXRecLockIsOwner(&lock->lockRecursive);
}
Bool
MXUser_IsLockedByCurThreadRecLock(const MXUserRecLock *lock) // IN:
{
- return MXRecLockIsOwner(&lock->basic);
+ return MXRecLockIsOwner(&lock->lockRecursive);
}
#include "ulInt.h"
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserDumpRWLock
+ *
+ * Dump an read-write lock.
+ *
+ * Results:
+ * A dump.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+MXUserDumpRWLock(MXUserHeader *header) // IN:
+{
+ uint32 i;
+ MXUserRWLock *lock = (MXUserRWLock *) header;
+
+ Warning("%s: Read-write lock @ %p\n", __FUNCTION__, lock);
+
+ Warning("\tsignature %X\n", lock->lockHeader.lockSignature);
+ Warning("\tname %s\n", lock->lockHeader.lockName);
+ Warning("\trank %d\n", lock->lockHeader.lockRank);
+
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ Warning("\tlockReadWrite %p\n", &lock->lockReadWrite);
+#else
+ Warning("\tcount %u\n", lock->lockRecursive.lockCount);
+
+#if defined(VMX86_DEBUG)
+ Warning("\tcaller %p\n", lock->lockRecursive.lockCaller);
+ Warning("\tVThreadID %d\n", (int) lock->lockRecursive.lockVThreadID);
+#endif
+#endif
+
+ for (i = 0; i < VTHREAD_MAX_THREADS; i++) {
+ if (lock->lockTaken[i] != RW_UNLOCKED) {
+ Warning("\tlockTaken[%d] %u\n", i, lock->lockTaken[i]);
+ }
+ }
+}
+
+
/*
*-----------------------------------------------------------------------------
*
properName = Util_SafeStrdup(userName);
}
+ lock->lockHeader.lockName = properName;
+ lock->lockHeader.lockSignature = USERLOCK_SIGNATURE;
+ lock->lockHeader.lockRank = rank;
+ lock->lockHeader.lockDumper = MXUserDumpRWLock;
+
#if defined(PTHREAD_RWLOCK_INITIALIZER)
- if (pthread_rwlock_init(&lock->lockObject, NULL) != 0) {
+ /* Initialize the native read-write lock */
+ if (pthread_rwlock_init(&lock->lockReadWrite, NULL) != 0) {
free((void *) properName);
free(lock);
lock = NULL;
}
-#endif
-
- /* Establish standard header. This may get used for real too. */
- if (!MXRecLockInit(&lock->lockRecursive, properName, rank)) {
+#else
+ /* Create recursive lock used for emulation */
+ if (!MXRecLockInit(&lock->lockRecursive)) {
free((void *) properName);
free(lock);
lock = NULL;
}
+#endif
return lock;
}
VThreadID self = VThread_CurID();
- ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
#if defined(PTHREAD_RWLOCK_INITIALIZER)
- err = pthread_rwlock_rdlock(&lock->lockObject);
+ err = pthread_rwlock_rdlock(&lock->lockReadWrite);
if (err == 0) {
if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
- MXUserDumpAndPanic(&lock->lockRecursive,
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: AcquireForRead after AcquireForRead",
__FUNCTION__);
}
} else {
- MXUserDumpAndPanic(&lock->lockRecursive, "%s: %s",
+ MXUserDumpAndPanic(&lock->lockHeader, "%s: %s",
(err == EDEADLK) ? "Deadlock detected (%d)" :
"Internal error (%d)",
__FUNCTION__, err);
}
#else
- MXRecLockAcquire(&lock->lockRecursive, MXGetThreadID(), GetReturnAddress());
+ MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress());
if (lock->lockTaken[self] != RW_UNLOCKED) {
if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
- MXUserDumpAndPanic(&lock->lockRecursive,
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: AcquireForRead after AcquireForRead"
__FUNCTION__, self);
} else {
- MXUserDumpAndPanic(&lock->lockRecursive,
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: AcquireForRead after AcquireForWrite"
__FUNCTION__, self);
}
VThreadID self = VThread_CurID();
- ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
#if defined(PTHREAD_RWLOCK_INITIALIZER)
- err = pthread_rwlock_wrlock(&lock->lockObject);
+ err = pthread_rwlock_wrlock(&lock->lockReadWrite);
if (err != 0) {
- MXUserDumpAndPanic(&lock->lockRecursive, "%s: %s",
+ MXUserDumpAndPanic(&lock->lockHeader, "%s: %s",
(err == EDEADLK) ? "Deadlock detected (%d)" :
"Internal error (%d)",
__FUNCTION__, err);
}
#else
- MXRecLockAcquire(&lock->lockRecursive, MXGetThreadID(), GetReturnAddress());
+ MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress());
if (lock->lockTaken[self] != RW_UNLOCKED) {
if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
- MXUserDumpAndPanic(&lock->lockRecursive,
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: AcquireForRead after AcquireForWrite"
__FUNCTION__);
} else {
- MXUserDumpAndPanic(&lock->lockRecursive,
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: AcquireForWrite after AcquireForWrite"
__FUNCTION__);
}
VThreadID self = VThread_CurID();
uint8 myState = lock->lockTaken[self];
- ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
if (myState == RW_UNLOCKED) {
- MXUserDumpAndPanic(&lock->lockRecursive,
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: Release of read-lock not by owner (%d)",
__FUNCTION__, self);
}
ASSERT(MXUserIsAllUnlocked(lock));
}
- pthread_rwlock_unlock(&lock->lockObject);
+ pthread_rwlock_unlock(&lock->lockReadWrite);
#else
ASSERT(MXUserIsAllUnlocked(lock));
MXRecLockRelease(&lock->lockRecursive);
MXUser_DestroyRWLock(MXUserRWLock *lock) // IN:
{
if (lock != NULL) {
- ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
if (!MXUserIsAllUnlocked(lock)) {
- MXUserDumpAndPanic(&lock->lockRecursive,
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: Destroy on read-lock while still acquired",
__FUNCTION__);
}
#if defined(PTHREAD_RWLOCK_INITIALIZER)
- pthread_rwlock_destroy(&lock->lockObject);
+ pthread_rwlock_destroy(&lock->lockReadWrite);
+#else
+ MXRecLockDestroy(&lock->lockRecursive);
#endif
- MXRecLockDestroy(&lock->lockRecursive);
+ free((void *) lock->lockHeader.lockName);
free(lock);
}
}
#include "ulInt.h"
-/*
- *-----------------------------------------------------------------------------
- *
- * MXUserReleaseExclLock --
- *
- * Release (unlock) a lock.
- *
- * Results:
- * The lock is released.
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-static INLINE void
-MXUserReleaseExclLock(MXRecLock *lock, // IN/OUT:
- char *type) // IN:
-{
- if (!MXRecLockIsOwner(lock)) {
- if (MXRecLockCount(lock) == 0) {
- MXUserDumpAndPanic(lock, "%s: Release of an unacquired %s lock",
- __FUNCTION__, type);
- } else {
- MXUserDumpAndPanic(lock, "%s: Release of owned %s lock",
- __FUNCTION__, type);
- }
- }
-
- MXRecLockRelease(lock);
-}
-
-
/*
*-----------------------------------------------------------------------------
*
void
MXUser_ReleaseExclLock(MXUserExclLock *lock) // IN/OUT:
{
- MXUserReleaseExclLock(&lock->basic, "exclusive");
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ if (!MXRecLockIsOwner(&lock->lockRecursive)) {
+ if (MXRecLockCount(&lock->lockRecursive) == 0) {
+ MXUserDumpAndPanic(&lock->lockHeader,
+ "%s: Release of an unacquired exclusive lock",
+ __FUNCTION__);
+ } else {
+ MXUserDumpAndPanic(&lock->lockHeader,
+ "%s: Release of owned exclusive lock",
+ __FUNCTION__);
+ }
+ }
+
+ MXRecLockRelease(&lock->lockRecursive);
}
void
MXUser_ReleaseRecLock(MXUserRecLock *lock) // IN/OUT:
{
- MXUserReleaseExclLock(&lock->basic, "recursive");
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ if (!MXRecLockIsOwner(&lock->lockRecursive)) {
+ if (MXRecLockCount(&lock->lockRecursive) == 0) {
+ MXUserDumpAndPanic(&lock->lockHeader,
+ "%s: Release of an unacquired recursive lock",
+ __FUNCTION__);
+ } else {
+ MXUserDumpAndPanic(&lock->lockHeader,
+ "%s: Release of owned recursive lock",
+ __FUNCTION__);
+ }
+ }
+
+ MXRecLockRelease(&lock->lockRecursive);
}
{
Bool success;
- success = MXRecLockTryAcquire(&lock->basic, MXGetThreadID(),
- GetReturnAddress());
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
- if (success && (MXRecLockCount(&lock->basic) > 1)) {
- MXUserDumpAndPanic(&lock->basic,
+ success = MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress());
+
+ if (success && (MXRecLockCount(&lock->lockRecursive) > 1)) {
+ MXUserDumpAndPanic(&lock->lockHeader,
"%s: Acquire on an acquired exclusive lock",
__FUNCTION__);
}
Bool
MXUser_TryAcquireRecLock(MXUserRecLock *lock) // IN/OUT:
{
- return MXRecLockTryAcquire(&lock->basic, MXGetThreadID(),
- GetReturnAddress());
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ return MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress());
}
#include "x86cpuid.h"
#endif
-#include "syncMutex.h"
#include "unicode.h"
#include "guest_os.h"
#include "dynbuf.h"
+++ /dev/null
-################################################################################
-### Copyright 2007 VMware, Inc. All rights reserved.
-###
-### This program is free software; you can redistribute it and/or modify
-### it under the terms of version 2 of the GNU General Public License as
-### published by the Free Software Foundation.
-###
-### This program is distributed in the hope that it will be useful,
-### but WITHOUT ANY WARRANTY; without even the implied warranty of
-### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-### GNU General Public License for more details.
-###
-### You should have received a copy of the GNU General Public License
-### along with this program; if not, write to the Free Software
-### Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-################################################################################
-
-noinst_LTLIBRARIES = libSync.la
-
-libSync_la_SOURCES =
-libSync_la_SOURCES += syncMutexPthread.c
-
+++ /dev/null
-/*********************************************************
- * Copyright (C) 1998 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *********************************************************/
-
-/*
- * syncMutexPthread.c --
- *
- * Implements a non-recursive mutex using pthreads
- */
-
-#include <pthread.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "vm_assert.h"
-#include "syncMutex.h"
-#include "util.h"
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncMutex_Init --
- *
- * Initializes a mutex structure. The 'path' parameter names the
- * mutex. If 'path' is NULL, then an anonymous mutex is
- * created. (see SyncWaitQ_Init)
- *
- * Results:
- * TRUE on success and FALSE otherwise
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-SyncMutex_Init(SyncMutex *that, // OUT:
- char const *path) // IN:
-{
- int error;
-
- error = pthread_mutex_init(&that->_mutex, NULL);
- if (error != 0) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncMutex_Destroy --
- *
- * Frees members of the specified mutex structure
- * (see SyncWaitQ_Destroy for side effects)
- *
- *----------------------------------------------------------------------
- */
-
-void
-SyncMutex_Destroy(SyncMutex *that) // IN:
-{
-#ifdef VMX86_DEBUG
- int error =
-#endif
- pthread_mutex_destroy(&that->_mutex);
-#ifdef VMX86_DEBUG
- ASSERT(error != EBUSY);
-#endif
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncMutex_Lock --
- *
- * Obtains the mutex
- *
- * Results:
- * TRUE on success and FALSE otherwise
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-SyncMutex_Lock(SyncMutex *that) // IN
-{
- int error = pthread_mutex_lock(&that->_mutex);
-
- ASSERT(error != EINVAL);
- if (error != 0) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncMutex_Unlock --
- *
- * Releases the mutex
- *
- * Results:
- * TRUE on success and FALSE otherwise
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-SyncMutex_Unlock(SyncMutex *that) // IN
-{
- int error = pthread_mutex_unlock(&that->_mutex);
-
- ASSERT(error != EINVAL);
- if (error != 0) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncMutex_Trylock --
- *
- * Tries to lock the mutex. Returns without blocking.
- *
- * Results:
- * TRUE if the mutex was locked, FALSE otherwise.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-SyncMutex_Trylock(SyncMutex *that) // IN:
-{
- ASSERT(that);
-#ifdef VMX86_SERVER
- NOT_IMPLEMENTED();
- return FALSE;
-#else
- return (0 == pthread_mutex_trylock(&that->_mutex));
-#endif
-}
libvmtools_la_LIBADD += ../lib/rpcOut/libRpcOut.la
libvmtools_la_LIBADD += ../lib/rpcVmx/libRpcVmx.la
libvmtools_la_LIBADD += ../lib/string/libString.la
-libvmtools_la_LIBADD += ../lib/sync/libSync.la
libvmtools_la_LIBADD += ../lib/syncDriver/libSyncDriver.la
libvmtools_la_LIBADD += ../lib/system/libSystem.la
libvmtools_la_LIBADD += ../lib/stubs/libStubsCS.la
COMMON += ../lib/dict/libDict.la
COMMON += ../lib/message/libMessage.la
COMMON += ../lib/unicode/libUnicode.la
-COMMON += ../lib/sync/libSync.la
COMMON += ../lib/lock/libLock.la
COMMON += ../lib/nothread/libNothread.la
COMMON += ../lib/misc/libMisc.la
vmware_user_LDADD += ../lib/rpcVmx/libRpcVmx.la
vmware_user_LDADD += ../lib/SLPv2Parser/libSLPv2Parser.la
vmware_user_LDADD += ../lib/string/libString.la
-vmware_user_LDADD += ../lib/sync/libSync.la
vmware_user_LDADD += ../lib/syncDriver/libSyncDriver.la
vmware_user_LDADD += ../lib/system/libSystem.la
if ENABLE_UNITY