. Start using lib/lock, a new user-level lock library that supports lock ranks.
. Change desktop background color when in Unity mode to light gray (not yet
implemented on X11).
. Remove lib/sync (replaced with lib/lock).
. Sync up vmxnet3 with upstreamed driver: Use API provided by Linux wherever
possible.
. Changes in shared code that don't affect open-vm-tools functionality.
Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
AC_SUBST([LIB_FILE_CPPFLAGS])
AC_SUBST([LIB_HGFS_SERVER_CPPFLAGS])
AC_SUBST([LIB_IMPERSONATE_CPPFLAGS])
+AC_SUBST([LIB_LOCK_CPPFLAGS])
AC_SUBST([LIB_MISC_CPPFLAGS])
+AC_SUBST([LIB_NOTHREAD_CPPFLAGS])
AC_SUBST([LIB_PROC_MGR_CPPFLAGS])
AC_SUBST([LIB_STRING_CPPFLAGS])
AC_SUBST([LIB_USER_CPPFLAGS])
lib/hgfsServerPolicyGuest/Makefile \
lib/image/Makefile \
lib/impersonate/Makefile \
+ lib/lock/Makefile \
lib/message/Makefile \
lib/misc/Makefile \
lib/netUtil/Makefile \
+ lib/nothread/Makefile \
lib/panic/Makefile \
lib/panicDefault/Makefile \
lib/printer/Makefile \
SUBDIRS += image
endif
SUBDIRS += impersonate
+SUBDIRS += lock
SUBDIRS += message
SUBDIRS += misc
SUBDIRS += netUtil
+SUBDIRS += nothread
SUBDIRS += panic
SUBDIRS += panicDefault
SUBDIRS += printer
#include "file.h"
#include "util.h"
#include "wiper.h"
-#include "syncMutex.h"
+#include "userlock.h"
#include "hgfsDirNotify.h"
#if defined(_WIN32)
Bool found = FALSE;
HgfsFileNode *fileNode = NULL;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
fileNode = HgfsHandle2FileNode(handle, session);
if (fileNode == NULL) {
goto exit;
found = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return found;
}
Bool found = FALSE;
HgfsFileNode *fileNode = NULL;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
fileNode = HgfsHandle2FileNode(handle, session);
if (fileNode == NULL) {
goto exit;
found = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return found;
}
ASSERT(localId);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
fileNode = HgfsHandle2FileNode(handle, session);
if (fileNode == NULL) {
goto exit;
found = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return found;
}
ASSERT(lock);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
fileNode = HgfsHandle2FileNode(handle, session);
if (fileNode == NULL) {
goto exit;
found = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return found;
#else
ASSERT(session);
ASSERT(session->nodeArray);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
for (i = 0; i < session->numNodes; i++) {
existingFileNode = &session->nodeArray[i];
if ((existingFileNode->state == FILENODE_STATE_IN_USE_CACHED) &&
}
}
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return found;
}
return found;
}
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
existingFileNode = HgfsHandle2FileNode(handle, session);
if (existingFileNode == NULL) {
goto exit_unlock;
found = (nameStatus == HGFS_NAME_STATUS_COMPLETE);
exit_unlock:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return found;
}
return found;
}
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
existingFileNode = HgfsHandle2FileNode(handle, session);
if (existingFileNode == NULL) {
goto exit_unlock;
found = TRUE;
exit_unlock:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
*fileName = name;
*fileNameSize = nameSize;
+
return found;
}
ASSERT(session);
ASSERT(session->nodeArray);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
for (i = 0; i < session->numNodes; i++) {
HgfsFileNode *existingFileNode = &session->nodeArray[i];
if ((existingFileNode->state == FILENODE_STATE_IN_USE_CACHED) &&
}
}
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return found;
#else
return FALSE;
ASSERT(copy);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
original = HgfsHandle2FileNode(handle, session);
if (original == NULL) {
goto exit;
found = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return found;
}
ASSERT(sequentialOpen);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
node = HgfsHandle2FileNode(handle, session);
if (node == NULL) {
goto exit;
success = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return success;
}
ASSERT(sharedFolderOpen);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
node = HgfsHandle2FileNode(handle, session);
if (node == NULL) {
goto exit;
success = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return success;
}
HgfsFileNode *node;
Bool updated = FALSE;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
node = HgfsHandle2FileNode(handle, session);
if (node == NULL) {
goto exit;
updated = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return updated;
}
ASSERT(session);
ASSERT(session->nodeArray);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
for (i = 0; i < session->numNodes; i++) {
existingFileNode = &session->nodeArray[i];
if (existingFileNode->state != FILENODE_STATE_UNUSED) {
}
}
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return updated;
}
HgfsFileNode *node;
Bool updated = FALSE;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
node = HgfsHandle2FileNode(handle, session);
if (node == NULL) {
goto exit;
updated = TRUE;
exit:
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
+
return updated;
}
HgfsFreeFileNode(HgfsHandle handle, // IN: Handle to free
HgfsSessionInfo *session) // IN: Session info
{
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
HgfsFreeFileNodeInternal(handle, session);
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
}
{
Bool allowed;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
allowed = session->numCachedLockedNodes < MAX_LOCKED_FILENODES;
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return allowed;
}
ASSERT(copy);
- SyncMutex_Lock(&session->searchArrayLock);
+ MXUser_AcquireExclLock(session->searchArrayLock);
original = HgfsSearchHandle2Search(handle, session);
if (original == NULL) {
goto exit;
found = TRUE;
exit:
- SyncMutex_Unlock(&session->searchArrayLock);
+ MXUser_ReleaseExclLock(session->searchArrayLock);
return found;
}
HgfsSearch *search;
Bool success = FALSE;
- SyncMutex_Lock(&session->searchArrayLock);
+ MXUser_AcquireExclLock(session->searchArrayLock);
+
search = HgfsSearchHandle2Search(handle, session);
if (search != NULL) {
HgfsRemoveSearchInternal(search, session);
success = TRUE;
}
- SyncMutex_Unlock(&session->searchArrayLock);
+
+ MXUser_ReleaseExclLock(session->searchArrayLock);
return success;
}
HgfsSearch *search;
DirectoryEntry *dent = NULL;
- SyncMutex_Lock(&session->searchArrayLock);
+ MXUser_AcquireExclLock(session->searchArrayLock);
+
search = HgfsSearchHandle2Search(handle, session);
if (search == NULL || search->dents == NULL) {
goto out;
}
out:
- SyncMutex_Unlock(&session->searchArrayLock);
+ MXUser_ReleaseExclLock(session->searchArrayLock);
return dent;
}
newBufferLen = strlen(newLocalName);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
for (i = 0; i < session->numNodes; i++) {
fileNode = &session->nodeArray[i];
fileNode->utf8NameLen = newBufferLen;
}
}
- SyncMutex_Unlock(&session->nodeArrayLock);
+
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
}
* Initialize all our locks first as these can fail.
*/
- if (!SyncMutex_Init(&session->fileIOLock, NULL)) {
+ session->fileIOLock = MXUser_CreateExclLock("HgfsFileIOLock",
+ RANK_UNRANKED);
+ if (session->fileIOLock == NULL) {
free(session);
LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
return FALSE;
}
- if (!SyncMutex_Init(&session->nodeArrayLock, NULL)) {
- SyncMutex_Destroy(&session->fileIOLock);
+
+ session->nodeArrayLock = MXUser_CreateExclLock("HgfsNodeArrayLock",
+ RANK_UNRANKED);
+ if (session->nodeArrayLock == NULL) {
+ MXUser_DestroyExclLock(session->fileIOLock);
free(session);
LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
return FALSE;
}
- if (!SyncMutex_Init(&session->searchArrayLock, NULL)) {
- SyncMutex_Destroy(&session->fileIOLock);
- SyncMutex_Destroy(&session->nodeArrayLock);
+
+ session->searchArrayLock = MXUser_CreateExclLock("HgfsSearchArrayLock",
+ RANK_UNRANKED);
+ if (session->searchArrayLock == NULL) {
+ MXUser_DestroyExclLock(session->fileIOLock);
+ MXUser_DestroyExclLock(session->nodeArrayLock);
free(session);
LOG(4, ("%s: Could not create search array sync mutex.\n", __FUNCTION__));
/* Remove, typically, the last reference, will teardown everything. */
HgfsServerSessionPut(session);
-
}
ASSERT(session->nodeArray);
ASSERT(session->searchArray);
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
LOG(4, ("%s: exiting.\n", __FUNCTION__));
/* Recycle all nodes that are still in use, then destroy the node pool. */
free(session->nodeArray);
session->nodeArray = NULL;
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
- /* Recycle all searches that are still in use, then destroy the search pool. */
- SyncMutex_Lock(&session->searchArrayLock);
+ /*
+ * Recycle all searches that are still in use, then destroy the
+ * search pool.
+ */
+
+ MXUser_AcquireExclLock(session->searchArrayLock);
for (i = 0; i < session->numSearches; i++) {
if (DblLnkLst_IsLinked(&session->searchArray[i].links)) {
free(session->searchArray);
session->searchArray = NULL;
- SyncMutex_Unlock(&session->searchArrayLock);
+ MXUser_ReleaseExclLock(session->searchArrayLock);
/* Teardown the locks for the sessions and destroy itself. */
- SyncMutex_Destroy(&session->nodeArrayLock);
- SyncMutex_Destroy(&session->searchArrayLock);
- SyncMutex_Destroy(&session->fileIOLock);
+ MXUser_DestroyExclLock(session->nodeArrayLock);
+ MXUser_DestroyExclLock(session->searchArrayLock);
+ MXUser_DestroyExclLock(session->fileIOLock);
free(session);
}
LOG(4, ("%s: Beginning\n", __FUNCTION__));
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
/*
* Iterate over each node, skipping those that are unused. For each node,
}
}
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
- SyncMutex_Lock(&session->searchArrayLock);
+ MXUser_AcquireExclLock(session->searchArrayLock);
/*
* Iterate over each search, skipping those that are on the free list. For
}
}
- SyncMutex_Unlock(&session->searchArrayLock);
+ MXUser_ReleaseExclLock(session->searchArrayLock);
LOG(4, ("%s: Ending\n", __FUNCTION__));
}
unsigned int i;
HgfsSearch *search;
- SyncMutex_Lock(&session->searchArrayLock);
+ MXUser_AcquireExclLock(session->searchArrayLock);
+
search = HgfsSearchHandle2Search(searchHandle, session);
if (search != NULL) {
Log("%s: %u dents in \"%s\"\n", __FUNCTION__, search->numDents,
Log("\"%s\"\n", search->dents[i]->d_name);
}
}
- SyncMutex_Unlock(&session->searchArrayLock);
+
+ MXUser_ReleaseExclLock(session->searchArrayLock);
#endif
}
ASSERT(handle);
ASSERT(shareName);
- SyncMutex_Lock(&session->searchArrayLock);
+ MXUser_AcquireExclLock(session->searchArrayLock);
+
search = HgfsAddNewSearch(baseDir, DIRECTORY_SEARCH_TYPE_DIR, shareName,
rootDir, session);
if (!search) {
*handle = HgfsSearch2SearchHandle(search);
out:
- SyncMutex_Unlock(&session->searchArrayLock);
+ MXUser_ReleaseExclLock(session->searchArrayLock);
return status;
}
ASSERT(cleanupName);
ASSERT(handle);
- SyncMutex_Lock(&session->searchArrayLock);
+ MXUser_AcquireExclLock(session->searchArrayLock);
+
search = HgfsAddNewSearch("", type, "", "", session);
if (!search) {
LOG(4, ("%s: failed to get new search\n", __FUNCTION__));
*handle = HgfsSearch2SearchHandle(search);
out:
- SyncMutex_Unlock(&session->searchArrayLock);
+ MXUser_ReleaseExclLock(session->searchArrayLock);
return status;
}
{
Bool removed = FALSE;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
removed = HgfsRemoveFromCacheInternal(handle, session);
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return removed;
}
{
Bool cached = FALSE;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
cached = HgfsIsCachedInternal(handle, session);
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return cached;
}
{
Bool added = FALSE;
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
added = HgfsAddToCacheInternal(handle, session);
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return added;
}
sharedFolderOpen = TRUE;
}
- SyncMutex_Lock(&session->nodeArrayLock);
+ MXUser_AcquireExclLock(session->nodeArrayLock);
+
node = HgfsAddNewFileNode(openInfo, localId, fileDesc, append, len,
openInfo->cpName, sharedFolderOpen, session);
if (node == NULL) {
LOG(4, ("%s: Failed to add new node.\n", __FUNCTION__));
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return FALSE;
}
if (!HgfsAddToCacheInternal(handle, session)) {
LOG(4, ("%s: Failed to add node to the cache.\n", __FUNCTION__));
- SyncMutex_Unlock(&session->nodeArrayLock);
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
return FALSE;
}
- SyncMutex_Unlock(&session->nodeArrayLock);
+
+ MXUser_ReleaseExclLock(session->nodeArrayLock);
/* Only after everything is successful, save the handle in the open info. */
openInfo->file = handle;
#include "cpName.h" // for HgfsNameStatus
#include "hgfsServerPolicy.h"
#include "hgfsUtil.h" // for HgfsInternalStatus
-#include "syncMutex.h"
+#include "userlock.h"
/*
* Does this platform have oplock support? We define it here to avoid long
HgfsSessionSendFunc *send;
/* Lock to ensure some fileIO requests are atomic for a handle. */
- SyncMutex fileIOLock;
+ MXUserExclLock *fileIOLock;
Atomic_uint32 refCount; /* Reference count for session. */
* Lock for the following 6 fields: the node array,
* counters and lists for this session.
*/
- SyncMutex nodeArrayLock;
+ MXUserExclLock *nodeArrayLock;
/* Open file nodes of this session. */
HgfsFileNode *nodeArray;
* Lock for the following three fields: for the search array
* and it's counter and list, for this session.
*/
- SyncMutex searchArrayLock;
+ MXUserExclLock *searchArrayLock;
/* Directory entry cache for this session. */
HgfsSearch *searchArray;
#include "posix.h"
#include "file.h"
#include "util.h"
-#include "syncMutex.h"
+#include "userlock.h"
#include "su.h"
#include "codeset.h"
#include "unicodeOperations.h"
* Seek to the offset and read from the file. Grab the IO lock to make
* this and the subsequent read atomic.
*/
- SyncMutex_Lock(&session->fileIOLock);
+
+ MXUser_AcquireExclLock(session->fileIOLock);
+
if (!sequentialOpen) {
# ifdef linux
{
status = errno;
LOG(4, ("%s: could not seek to %"FMT64"u: %s\n", __FUNCTION__,
offset, strerror(status)));
- SyncMutex_Unlock(&session->fileIOLock);
+ MXUser_ReleaseExclLock(session->fileIOLock);
goto error;
}
}
error = read(fd, payload, requiredSize);
- SyncMutex_Unlock(&session->fileIOLock);
+ MXUser_ReleaseExclLock(session->fileIOLock);
#endif
if (error < 0) {
status = errno;
* Seek to the offset and write from the file. Grab the IO lock to make
* this and the subsequent write atomic.
*/
- SyncMutex_Lock(&session->fileIOLock);
+
+ MXUser_AcquireExclLock(session->fileIOLock);
if (!sequentialOpen) {
# ifdef linux
{
status = errno;
LOG(4, ("%s: could not seek to %"FMT64"u: %s\n", __FUNCTION__,
offset, strerror(status)));
- SyncMutex_Unlock(&session->fileIOLock);
+ MXUser_ReleaseExclLock(session->fileIOLock);
goto error;
}
}
error = write(fd, payload, requiredSize);
- SyncMutex_Unlock(&session->fileIOLock);
+ MXUser_ReleaseExclLock(session->fileIOLock);
#endif
if (error < 0) {
status = errno;
#include <pthread.h>
#endif
+#include "util.h"
+
struct FoundryWorkerThread;
typedef void (*FoundryThreadProc)(struct FoundryWorkerThread *threadState);
EXTERN Bool Log_InitEx(const LogInitParams *params);
EXTERN void Log_Exit(void);
EXTERN void Log_SetConfigDir(const char *configDir);
-EXTERN void Log_SetLockFunc(void (*f)(Bool locking));
EXTERN void Log_WriteLogFile(const char *msg);
EXTERN Bool Log_Enabled(void);
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2000 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.
+ *
+ *********************************************************/
+
+#ifndef _MUTEX_H_
+#define _MUTEX_H_
+
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#ifdef _WIN32
+#include <WTypes.h> // for HANDLE
+#endif
+
+#include "vm_atomic.h"
+#include "vthread.h"
+#if defined VMM && defined VMCORE
+#include "mon_types.h"
+#include "x86regname.h"
+#endif
+
+#if defined VMM || defined VMX86_VMX
+#include "vprobe_static.h"
+#define VMM_VMX_ONLY(x) x
+#else
+#define VMM_VMX_ONLY(x)
+#endif
+
+/*
+ * mutex.h --
+ *
+ * This is the header file for mutual exclusion locks ("mutexes").
+ * These locks can be used by both monitor and user level code.
+ *
+ * We provide two variants: regular locks and recursive locks. The
+ * latter can be reacquired by the owning thread, in a counting manner.
+ *
+ * In optimized builds, locks are minimal and fast. In debug builds,
+ * we maintain additional information to catch improper use of locks.
+ *
+ */
+
+/* If adjusting MX_MAX_LOCKS, also adjust VMK's RPC_MAX_WORLD_CONNECTIONS. */
+#define MX_MAX_LOCKS 160 /* Max # of locks supported */
+#define MX_MAX_NAME_LEN 16 /* Max lock/condvar name len incl. zero. */
+
+/*
+ * On linux, semaphore use a pipe for waiting/waking up. If the pipe fills
+ * up, a thread doing a V() can block, which is not very nice. Which is
+ * why we cap the number of signals that a semaphore can accumulate.
+ */
+
+#define MX_MAX_SEMASIGNALS 64 /* Max #of accumulated signals in a counting sema. */
+
+typedef uint32 MX_LockID;
+typedef uint8 MXCVLink;
+
+typedef struct MXCVQueue {
+ MXCVLink head;
+ MXCVLink tail;
+ uint8 nsigs;
+ uint8 nwaits;
+} MXCVQueue;
+
+typedef union MXCVWord { /* Private to this module. */
+ uint32 all;
+ Atomic_uint32 atomic;
+ MXCVQueue s;
+} MXCVWord;
+
+/*
+ * The detail-level of stats collection is compile-time selectable.
+ * 0: no stats collected
+ * 1: samples lock usage at each timer tick
+ * 2: count blocking/nonblocking lock operations
+ * 3: like level 2, but additionally collect call chains.
+ * The defaults for the various builds are: obj = 2, opt = 1, others = 0
+ * Lock stats are currently disabled for opt builds. Will reenable soon.
+ */
+
+#if defined VMX86_VMX || defined VMM
+#define MX_STATS_LEVEL \
+ (vmx86_stats ? (vmx86_debug ? 2 : 1) : 0)
+#else
+#define MX_STATS_LEVEL 0
+#endif
+
+#if MX_STATS_LEVEL > 0
+#define MX_STATS_ONLY(x) x
+#else
+#define MX_STATS_ONLY(x)
+#endif
+
+/* When we compile with debugging or lock stats, we include extra fields. */
+#define MX_FAT_LOCKS (vmx86_debug || MX_STATS_LEVEL > 1)
+
+#if MX_FAT_LOCKS != 0
+#define MX_FAT_LOCKS_ONLY(x) x
+#else
+#define MX_FAT_LOCKS_ONLY(x)
+#endif
+
+/*
+ * For 64-bit Windows, the single 64-bit semaphore handle is spread
+ * across waitHandle (lower half) and signalHandle (upper half). For
+ * 32-bit Windows, the single 32-bit semaphore handle is stored in
+ * waitHandle. POSIX platforms use two 32-bit fds, waitHandle and
+ * signalHandle.
+ *
+ * #ifdefs and unions are avoided here because of offsetChecker
+ * limitations and padding issues. Wrapper functions for Windows
+ * provide get/set access to the handle.
+ */
+
+typedef struct MXSemaphore {
+ int waitHandle;
+ int signalHandle;
+ Atomic_uint32 signalled;
+ uint32 pad;
+#if MX_FAT_LOCKS != 0
+ uint64 blockTime;
+#endif
+} MXSemaphore;
+
+/*
+ * Although we define these types in a public header file, code
+ * in other modules should never access the lock fields directly.
+ */
+
+typedef struct MX_Mutex {
+ Atomic_uint32 nthreads; /* #threads interested in lock; incl. owner. */
+ MX_LockID lid; /* Unique id of lock; set at lock init time. */
+ MX_Rank rank; /* Rank of this lock; immutable. */
+ uint32 _pad; /* pad to 8-byte boundary. */
+#if MX_FAT_LOCKS != 0
+ Bool tracing; /* True iff tracing is enabled for this lock. */
+ VThreadID owner; /* Thread that currently holds lock (if any).
+ * Only used for assertion purposes. */
+ uint64 ip; /* R/EIP where lock was acquired. */
+#endif
+} MX_Mutex;
+
+typedef struct MX_MutexRec {
+ MX_Mutex lck; /* The core lock in this recursive mutex. */
+ VThreadID owner; /* Owner thr. if lock held; else invalid id. */
+ unsigned count; /* Number of times currently locked. */
+} MX_MutexRec;
+
+typedef struct MX_Condvar {
+ MXCVWord cvword; /* Semantics private to this module. */
+#if MX_FAT_LOCKS != 0
+ char name[MX_MAX_NAME_LEN]; /* Zero-terminated name for condvar. */
+#endif
+} MX_Condvar;
+
+typedef struct MX_Barrier {
+ MX_Mutex lck; /* Lock that protects barrier state. */
+ MX_Condvar cv; /* Threads wait here for barrier to saturate. */
+ unsigned threshold; /* Barrier threshold; set at init time only. */
+ unsigned nEntered; /* Number of threads that have reached barrier. */
+ MX_FAT_LOCKS_ONLY(uint32 _pad;)
+} MX_Barrier;
+
+typedef struct MX_BinSemaphore {
+ MXSemaphore sema;
+ MX_Rank rank;
+ Atomic_uint32 signalled;
+#if MX_FAT_LOCKS != 0
+ char name[MX_MAX_NAME_LEN]; /* Name of binary semaphore. */
+#endif
+} MX_BinSemaphore;
+
+typedef struct MX_CountingSemaphore {
+ MXSemaphore sema;
+ MX_Rank rank;
+ uint32 _pad;
+#if MX_FAT_LOCKS != 0
+ char name[MX_MAX_NAME_LEN]; /* Name of counting semaphore. */
+#endif
+} MX_CountingSemaphore;
+
+#if MX_STATS_LEVEL > 0
+EXTERN MX_Mutex *curLock;
+EXTERN void MXInitLockStats(const char *name, MX_Mutex *lck);
+#else
+#define MXInitLockStats(name, lck)
+#endif
+
+#if MX_STATS_LEVEL > 1
+EXTERN void MX_LogStats(unsigned epoch);
+#else
+#define MX_LogStats(epoch)
+#endif
+
+#if MX_FAT_LOCKS != 0
+EXTERN void MXInitLockFat(const char *name, MX_Rank rank, MX_Mutex *lck);
+EXTERN void MXAcquiredLock(MX_Mutex *lck, Bool blocking);
+EXTERN void MX_AssertNoLocksHeld(Bool checkPendingLocks);
+EXTERN void MXInitCondvarFat(const char *name, MX_Condvar *cv);
+EXTERN void MX_CheckRank(MX_Rank rank, const char *name);
+EXTERN void MX_CheckRankWithBULL(MX_MutexRec *lock, Bool belowUser);
+EXTERN Bool MX_IsLockedByThread(const MX_Mutex *lck, VThreadID tid);
+EXTERN Bool MX_IsLockedByCurThread(const MX_Mutex *lck);
+EXTERN MX_Rank MX_CurrentRank(void);
+#else
+/* Use macros to keep string arguments out of release builds. */
+#define MXInitLockFat(name, rank, lck)
+#define MXAcquiredLock(lck, blocking)
+#define MX_AssertNoLocksHeld(checkPendingLocks)
+#define MXInitCondvarFat(name, cv)
+#define MX_CheckRank(rank, name)
+#define MX_CheckRankWithBULL(lock, belowUser)
+#endif
+
+EXTERN void MXInitLockWork(MX_Mutex *lck, MX_Rank rank);
+EXTERN size_t MX_GetMXStateSize(void);
+EXTERN void MX_Init(void *mxStatePtr);
+EXTERN void MX_PlantThreadWatchDog(void (*func)(void));
+EXTERN void MX_InitPerThread(VThreadID tid);
+EXTERN void MX_ExitPerThread(VThreadID tid);
+EXTERN void MX_Shutdown(void);
+EXTERN void MX_Lock(MX_Mutex *lck);
+EXTERN void MX_Unlock(MX_Mutex *lck);
+EXTERN void MX_DestroyLock(MX_Mutex *lck);
+EXTERN void MX_LockRec(MX_MutexRec *lckr);
+EXTERN void MX_UnlockRec(MX_MutexRec *lckr);
+EXTERN Bool MX_TryLockRec(MX_MutexRec *lckr);
+EXTERN Bool MX_IsLockedByThreadRec(const MX_MutexRec *lckr, VThreadID tid);
+EXTERN Bool MX_IsLockedByCurThreadRec(const MX_MutexRec *lckr);
+EXTERN void MXInitCondvarWork(MX_Condvar *cv);
+EXTERN void MX_Signal(MX_Condvar *cv);
+EXTERN void MX_Broadcast(MX_Condvar *cv);
+EXTERN void MX_Wait(MX_Condvar *cv, MX_Mutex *lck);
+EXTERN void MX_WaitRec(MX_Condvar *cv, MX_MutexRec *lckr);
+EXTERN void MX_InitBarrier(MX_Barrier *br, MX_Rank rank, unsigned threshold);
+EXTERN void MX_EnterBarrier(MX_Barrier *br);
+#if !defined VMM
+EXTERN Bool MX_WaitTimeout(MX_Condvar *cv, MX_Mutex *lck, int maxWaitUS);
+EXTERN Bool MX_WaitRecTimeout(MX_Condvar *cv, MX_MutexRec *lckr, int maxWaitUS);
+#endif
+
+EXTERN void MX_InitBinSemaphore(const char *name, MX_Rank rank, MX_BinSemaphore *binSema);
+EXTERN MXSemaHandle MX_BinSemaphoreGetSemaHandle(MX_BinSemaphore *binSema);
+#ifdef _WIN32
+EXTERN void MX_BinSemaphoreSetSemaHandle(MX_BinSemaphore *binSema, MXSemaHandle h);
+#endif
+EXTERN void MX_DestroyBinSemaphore(MX_BinSemaphore *binSema);
+EXTERN void MX_BinSemaphoreWait(MX_BinSemaphore *binSema);
+#if !defined VMM
+EXTERN Bool MX_BinSemaphoreTryWaitTimeout(MX_BinSemaphore *binSema, int usTimeout);
+#endif
+EXTERN void MX_BinSemaphoreSignal(MX_BinSemaphore *binSema);
+EXTERN Bool MX_BinSemaphoreTryWait(MX_BinSemaphore *binSema);
+EXTERN void MX_InitCountingSemaphore(const char *name, MX_Rank rank, MX_CountingSemaphore *csema);
+EXTERN void MX_DestroyCountingSemaphore(MX_CountingSemaphore *csema);
+EXTERN void MX_CountingSemaphoreWait(MX_CountingSemaphore *csema);
+EXTERN void MX_CountingSemaphoreSignal(MX_CountingSemaphore *csema);
+EXTERN Bool MX_CountingSemaphoreTryWait(MX_CountingSemaphore *csema);
+
+#if defined VMM
+#ifdef VMX86_DEBUG
+EXTERN Bool prohibitBarriers;
+#endif
+EXTERN void MX_LockMarkEnd(void);
+EXTERN void MX_UnlockMarkEnd(void);
+#if defined VMCORE
+EXTERN void MX_LockCalloutStart(void);
+EXTERN void MX_LockCalloutEnd(void);
+EXTERN TCA MX_LockEmit(MX_Mutex *lck, TCA memptr);
+EXTERN TCA MX_UnlockEmit(MX_Mutex *lck, TCA memptr);
+EXTERN TCA MX_LockIndEmit(RegisterName reg, TCA memptr);
+EXTERN TCA MX_UnlockIndEmit(RegisterName reg, TCA memptr);
+EXTERN TCA MX_LockRecEmit(MX_MutexRec *lck, TCA memptr);
+EXTERN TCA MX_UnlockRecEmit(MX_MutexRec *lck, TCA memptr);
+EXTERN Bool MX_VCPUNeedsForceWakeup(Vcpuid vcpuid);
+EXTERN void MX_SemaphoreForceWakeup(Vcpuid vcpuid);
+#endif
+#else
+EXTERN Bool MX_PowerOn(void);
+EXTERN void MX_PowerOff(void);
+EXTERN Bool MX_IsInitialized(void);
+#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_InitLock --
+ * Initialize a lock.
+ * Use macros to keep strings out of release builds.
+ * Types: const char *name, MX_Rank rank, MX_Mutex *lck.
+ *----------------------------------------------------------------------
+ */
+
+#define MX_InitLock(name, rank, lck) \
+ do { \
+ MX_Mutex *_lck = (lck); \
+ \
+ /* Use two fcts to make name dead in release builds. */ \
+ MXInitLockWork(_lck, rank); \
+ MXInitLockFat((name), (rank), _lck); \
+ MXInitLockStats((name), _lck); \
+ } while (0)
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_IsLocked --
+ * Return TRUE iff "lck" is currently locked by some thread.
+ * Since this is an unstable property, except when it is known that
+ * the current thread holds the lock, this operation is mostly useful
+ * to assert that a lock is held (by the current thread).
+ *----------------------------------------------------------------------
+ */
+
+static INLINE Bool
+MX_IsLocked(MX_Mutex *lck) // IN:
+{
+ return Atomic_Read(&lck->nthreads) != 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_TryLock --
+ * Try to get a lock, but don't block if it is unavailable.
+ * Return TRUE if lock was successfully acquired, FALSE otherwise.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE Bool
+MX_TryLock(MX_Mutex *lck) // IN:
+{
+ /* This code was written to produce good code for MX_Lock().
+ If you change it, be sure to inspect the generated code. */
+ uint32 old = Atomic_ReadIfEqualWrite(&lck->nthreads, 0, 1);
+
+ if (old == 0) {
+#if MX_FAT_LOCKS != 0
+ {
+ lck->ip = (uint64)(uintptr_t) GetReturnAddress();
+ }
+#endif
+ MXAcquiredLock(lck, FALSE);
+ VMM_VMX_ONLY(VProbe_2Args(VPROBE_MX_LockAcquired, lck->lid, lck->rank));
+ }
+
+ return old == 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_SetTracing --
+ * Enable or disable tracing of activity on a lock.
+ * No-op in non-debug builds.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+MX_SetTracing(MX_Mutex *lck, // IN:
+ Bool t) // IN:
+{
+ DEBUG_ONLY(lck->tracing = t);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_InitLockRec --
+ * Initialize a recursive lock.
+ * Use macros to keep strings out of release builds.
+ * Types: const char *name, MX_Rank rank, MX_MutexRec *lckr
+ *----------------------------------------------------------------------
+ */
+
+#define MX_InitLockRec(name, rank, lckr) \
+ do { \
+ MX_MutexRec *_lckr = (lckr); \
+ MX_InitLock((name), (rank), &_lckr->lck); \
+ _lckr->owner = VTHREAD_INVALID_ID; \
+ _lckr->count = 0; \
+ } while (0)
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_IsLockedRec --
+ * Similar to "MX_IsLocked()" but applies to recursive locks.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE Bool
+MX_IsLockedRec(MX_MutexRec *lckr) // IN:
+{
+ return MX_IsLocked(&lckr->lck);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_SetTracingRec --
+ * Similar to "MX_SetTracing()" but applies to recursive locks.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+MX_SetTracingRec(MX_MutexRec *lckr, // IN:
+ Bool t) // IN:
+{
+ MX_SetTracing(&lckr->lck, t);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_DestroyLockRec --
+ * Like "MX_DestroyLock()" but applies to recursive mutex.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+MX_DestroyLockRec(MX_MutexRec *lckr) // IN:
+{
+ MX_DestroyLock(&lckr->lck);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_LockOwnerRec --
+ * Return the lock owner, or VTHREAD_INVALID_ID.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE VThreadID
+MX_LockOwnerRec(MX_MutexRec *lckr) // IN:
+{
+ return lckr->owner;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_InitCondvar --
+ * Initialize a condition variable.
+ * Use macro to keep strings out of release builds.
+ * Types: const char *name, MX_Condvar *cv.
+ *----------------------------------------------------------------------
+ */
+
+#define MX_InitCondvar(name, cv) \
+ do { \
+ MX_Condvar *_cv = (cv); \
+ MXInitCondvarWork(_cv); \
+ MXInitCondvarFat((name), _cv); \
+ } while (0)
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_DestroyBarrier --
+ * Release all resources held by a barrier.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+MX_DestroyBarrier(MX_Barrier *br) // IN:
+{
+ ASSERT(br->nEntered == 0);
+ MX_DestroyLock(&br->lck);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_GetRank --
+ * Returns a lock's rank.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE MX_Rank
+MX_GetRank(MX_Mutex *lock) // IN:
+{
+ ASSERT(lock != NULL);
+
+ return lock->rank;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ * MX_GetRankRec --
+ * Returns a recursive lock's rank.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE MX_Rank
+MX_GetRankRec(MX_MutexRec *lock) // IN:
+{
+ ASSERT(lock != NULL);
+
+ return MX_GetRank(&lock->lck);
+}
+
+
+#if defined VMM && defined VMCORE // {
+
+EXTERN int inSemaWait;
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MX_SemaphoreInWait --
+ * TRUE if this vcpu is waiting on any semaphore. This is currently used by
+ * the poweroff code to find out whether we are holding any (partial) locks.
+ *
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+MX_SemaphoreInWait(void)
+{
+ ASSERT(inSemaWait >= 0);
+
+ return inSemaWait > 0;
+}
+
+#endif // }
+
+#endif // _MUTEX_H_
Bool SyncMutex_Trylock(SyncMutex *that);
#endif
-SyncMutex *SyncMutex_CreateSingleton(Atomic_Ptr *lckStorage);
-
#endif // #ifndef _SYNC_MUTEX_H_
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+#ifndef _USERLOCK_H_
+#define _USERLOCK_H_
+
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#include "vm_atomic.h"
+#include "vm_basic_types.h"
+#include "vm_basic_defs.h"
+
+/*
+ * Statistics interfaces will come soon.
+ *
+ * Each lock is expected to keep:
+ * - Min
+ * - Max
+ * - Mean
+ * - S.D.
+ * - Histogram (log2?)
+ *
+ * for time-till-acquistion and time-locked.
+ */
+
+typedef struct MXUserExclLock MXUserExclLock;
+typedef struct MXUserRecLock MXUserRecLock;
+typedef struct MXUserRWLock MXUserRWLock;
+
+/*
+ * Exclusive ownership lock
+ */
+
+MXUserExclLock *
+MXUser_CreateExclLock(const char *name,
+ MX_Rank rank);
+
+void MXUser_AcquireExclLock(MXUserExclLock *lock);
+Bool MXUser_TryAcquireExclLock(MXUserExclLock *lock);
+void MXUser_ReleaseExclLock(MXUserExclLock *lock);
+void MXUser_DestroyExclLock(MXUserExclLock *lock);
+Bool MXUser_IsLockedByCurThreadExclLock(const MXUserExclLock *lock);
+
+MXUserExclLock *
+MXUser_CreateSingletonExclLock(Atomic_Ptr *lockStorage,
+ const char *name,
+ MX_Rank rank);
+
+/*
+ * Recursive lock.
+ */
+
+MXUserRecLock *
+MXUser_CreateRecLock(const char *name,
+ MX_Rank rank);
+
+void MXUser_AcquireRecLock(MXUserRecLock *lock);
+Bool MXUser_TryAcquireRecLock(MXUserRecLock *lock);
+void MXUser_ReleaseRecLock(MXUserRecLock *lock);
+void MXUser_DestroyRecLock(MXUserRecLock *lock);
+Bool MXUser_IsLockedByCurThreadRecLock(const MXUserRecLock *lock);
+
+MXUserRecLock *
+MXUser_CreateSingletonRecLock(Atomic_Ptr *lockStorage,
+ const char *name,
+ MX_Rank rank);
+
+/*
+ * Eventually there will be an API to bind an recursive MX lock to a
+ * MXUser recursive lock. This will allow such MXUser recursive locks
+ * to be used for Poll.
+ */
+
+/*
+ * Read-write lock
+ */
+
+MXUserRWLock *
+MXUser_CreateRWLock(const char *name,
+ MX_Rank rank);
+
+void MXUser_AcquireForRead(MXUserRWLock *lock);
+void MXUser_AcquireForWrite(MXUserRWLock *lock);
+void MXUser_ReleaseRWLock(MXUserRWLock *lock);
+void MXUser_DestroyRWLock(MXUserRWLock *lock);
+#endif // _USERLOCK_H_
--- /dev/null
+/*********************************************************
+ * Copyright (C) 1998-2003 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.
+ *
+ *********************************************************/
+
+/*
+ *
+ * vcpuid.h --
+ *
+ * Monitor's VCPU ID.
+ */
+
+#ifndef _VCPUID_H_
+#define _VCPUID_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_DISTRIBUTE
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#include "vm_basic_types.h"
+
+
+typedef uint32 Vcpuid; // VCPU number
+
+#define VCPUID_INVALID (~0U)
+
+#define BOOT_VCPU_ID 0
+#define IS_BOOT_VCPUID(vcpuid) ((vcpuid) == BOOT_VCPU_ID)
+#define IS_BOOT_VCPU() IS_BOOT_VCPUID(CurVcpuid())
+
+#define MAX_VCPUS 32
+
+
+#endif // ifndef _VCPUID_H_
VIX_E_WRAPPER_VERSION_NOT_FOUND = 22002,
VIX_E_WRAPPER_SERVICEPROVIDER_NOT_FOUND = 22003,
VIX_E_WRAPPER_PLAYER_NOT_INSTALLED = 22004,
+ VIX_E_WRAPPER_RUNTIME_NOT_INSTALLED = 22005,
/* FuseMnt errors*/
VIX_E_MNTAPI_MOUNTPT_NOT_FOUND = 24000,
#define hosted_lg_pg 0
#endif
+/*
+ * Basic lock ranks. Others are defined in mutexRank.h.
+ */
+
+#define RANK_UNRANKED 0
+#define RANK_userlevelLock 100
+#define RANK_LEAF 0xFFFE
+#define RANK_INVALID 0xFFFF
+
#endif // ifndef _VM_BASIC_DEFS_H_
# endif
#endif
+#ifdef __APPLE__
+/*
+ * Format specifier for all these annoying types such as {S,U}Int32
+ * which are 'long' in 32-bit builds
+ * and 'int' in 64-bit builds.
+ */
+# ifdef __LP64__
+# define FMTLI ""
+# else
+# define FMTLI "l"
+# endif
+
+/*
+ * Format specifier for all these annoying types such as NS[U]Integer
+ * which are 'int' in 32-bit builds
+ * and 'long' in 64-bit builds.
+ */
+# ifdef __LP64__
+# define FMTIL "l"
+# else
+# define FMTIL ""
+# endif
+#endif
+
+
/*
* Define MXSemaHandle here so both vmmon and vmx see this definition.
*/
} VMRect;
#endif
+/*
+ * ranked locks "everywhere"
+ */
+
+typedef uint32 MX_Rank;
+
#endif /* _VM_BASIC_TYPES_H_ */
#define WBC_VERSION "e.x.p"
#define SDK_VERSION "4.1.0"
#define FOUNDRY_VERSION "e.x.p"
-#define FOUNDRY_FILE_VERSION 1,8,0,PRODUCT_BUILD_NUMBER_NUMERIC
+#define FOUNDRY_FILE_VERSION 1,8,1,PRODUCT_BUILD_NUMBER_NUMERIC
#define VMLS_VERSION "e.x.p"
#define VLICENSE_VERSION "1.1.2"
#define DDK_VERSION "e.x.p"
#define SO_VMCI_BUFFER_MAX_SIZE 2
#define SO_VMCI_PEER_HOST_VM_ID 3
#define SO_VMCI_SERVICE_LABEL 4
+#define SO_VMCI_TRUSTED 5
/*
* The VMCI sockets address equivalents of INADDR_ANY. The first works for
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2002 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.
+ *
+ *********************************************************/
+
+/*
+ * vthread.h --
+ *
+ * Thread management
+ */
+
+#ifndef _VTHREAD_H_
+#define _VTHREAD_H_
+
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#include "vthreadBase.h"
+#include "vcpuid.h"
+
+#if VTHREAD_USE_PTHREAD
+#include <sys/types.h>
+#include <unistd.h>
+#include <pthread.h>
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+
+#if VTHREAD_MAX_VCPUS < MAX_VCPUS
+ #error VTHREAD_MAX_VCPUS < MAX_VCPUS
+#endif
+
+
+/*
+ * Scheduler priorities for VThread_SetThreadPriority().
+ */
+
+#if VTHREAD_USE_PTHREAD
+#ifdef __APPLE__
+// These values come from osfmk/kern/sched.h in xnu-792.6.70.
+# define VTHREAD_PRIORITY_IDLE 0
+# define VTHREAD_PRIORITY_LOWEST 11
+# define VTHREAD_PRIORITY_BELOW_NORMAL 21
+# define VTHREAD_PRIORITY_NORMAL 31
+# define VTHREAD_PRIORITY_ABOVE_NORMAL 41
+# define VTHREAD_PRIORITY_HIGHEST 51
+// TODO: This is just the highest a user thread can go; not really time critical.
+# define VTHREAD_PRIORITY_TIME_CRITICAL 63
+#else
+# define VTHREAD_PRIORITY_IDLE 19
+# define VTHREAD_PRIORITY_LOWEST 15
+# define VTHREAD_PRIORITY_BELOW_NORMAL 10
+# define VTHREAD_PRIORITY_NORMAL 0
+# define VTHREAD_PRIORITY_ABOVE_NORMAL (-10)
+# define VTHREAD_PRIORITY_HIGHEST (-15)
+# define VTHREAD_PRIORITY_TIME_CRITICAL (-20)
+#endif // !__APPLE__
+#endif
+#ifdef _WIN32
+# define VTHREAD_PRIORITY_IDLE THREAD_PRIORITY_IDLE
+# define VTHREAD_PRIORITY_LOWEST THREAD_PRIORITY_LOWEST
+# define VTHREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_BELOW_NORMAL
+# define VTHREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL
+# define VTHREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_ABOVE_NORMAL
+# define VTHREAD_PRIORITY_HIGHEST THREAD_PRIORITY_HIGHEST
+# define VTHREAD_PRIORITY_TIME_CRITICAL THREAD_PRIORITY_TIME_CRITICAL
+#endif
+
+
+/*
+ * Debuggable builds log per-thread timing info.
+ */
+
+#if (defined(VMX86_DEVEL) || defined(VMX86_DEBUG)) && defined(USERLEVEL)
+#define VTHREAD_RESOURCE_ACCOUNTING
+#endif
+
+
+/*
+ * Private variables
+ *
+ * Don't use these directly. Go through the proper interface
+ * functions.
+ */
+
+#ifdef VMM
+extern VThreadID vthreadCurID;
+#endif
+
+extern VThreadID vthreadMaxVCPUID;
+
+
+/*
+ * Global functions
+ */
+
+static INLINE Bool
+VThread_IsValidID(VThreadID tid) // IN: The thread id.
+{
+ return tid < VTHREAD_MAX_THREADS;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThread_CurID --
+ *
+ * Get the current thread ID. This is only inline for the monitor.
+ *
+ * Results:
+ * Thread ID.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifdef VMM
+static INLINE VThreadID
+VThread_CurID(void)
+{
+ ASSERT(VThread_IsValidID(vthreadCurID));
+
+ return vthreadCurID;
+}
+#endif
+
+
+static INLINE Bool
+VThread_IsVMXID(VThreadID tid) // IN: The thread id.
+{
+ return tid == VTHREAD_VMX_ID;
+}
+
+
+static INLINE Bool
+VThread_IsMKSID(VThreadID tid) // IN: The thread id.
+{
+ return tid == VTHREAD_MKS_ID;
+}
+
+
+static INLINE Bool
+VThread_IsVCPUID(VThreadID tid) // IN: The thread id.
+{
+ ASSERT(VThread_IsValidID(vthreadMaxVCPUID));
+
+ return tid >= VTHREAD_VCPU0_ID && tid < vthreadMaxVCPUID;
+}
+
+
+static INLINE Bool
+VThread_IsVMX(void)
+{
+ return VThread_IsVMXID(VThread_CurID());
+}
+
+
+static INLINE Bool
+VThread_IsMKS(void)
+{
+ return VThread_IsMKSID(VThread_CurID());
+}
+
+
+static INLINE Bool
+VThread_IsVCPU(void)
+{
+ return VThread_IsVCPUID(VThread_CurID());
+}
+
+
+static INLINE Bool
+VThread_IsVCPU0(void)
+{
+ return VThread_CurID() == VTHREAD_VCPU0_ID;
+}
+
+
+static INLINE Vcpuid
+VThread_ThreadIDToVCPUID(VThreadID tid) // IN: The thread id.
+{
+ ASSERT(VThread_IsVCPUID(tid));
+
+ return tid - VTHREAD_VCPU0_ID;
+}
+
+
+static INLINE VThreadID
+VThread_VCPUIDToThreadID(Vcpuid vcpuID)
+{
+ VThreadID threadID = VTHREAD_VCPU0_ID + vcpuID;
+
+ ASSERT(VThread_IsVCPUID(threadID));
+
+ return threadID;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThread_BestVCPUID --
+ *
+ * Return the "best" VCPU to use (for actions), which is
+ * either the current VCPU (if any) or some default.
+ *
+ * The monitor version needs to be a macro because of an include
+ * problem: CurVcpuid() is defined in monitor.h, which includes
+ * sharedAreaVCPU.h, which includes misc_shared.h,
+ * which includes mutex.h, which includes us.
+ *
+ * Results:
+ * The best VCPU ID.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifdef VMM
+#define VThread_BestVCPUID() CurVcpuid()
+
+#else
+#ifdef VCPUID_INVALID
+static INLINE Vcpuid
+VThread_BestVCPUID(void)
+{
+ VThreadID threadID = VThread_CurID();
+
+ return VThread_IsVCPUID(threadID) ? VThread_ThreadIDToVCPUID(threadID) :
+ BOOT_VCPU_ID;
+}
+#endif
+#endif
+
+
+#ifdef VMM // {
+
+/*
+ * Save a few bytes and inline VThread_MonitorInit().
+ *
+ * The VCPU ID and number of VCPU's are passed in because
+ * (it's the right thing to do, and) they require monitor.h,
+ * which includes mutex.h, which includes us.
+ * -- edward
+ */
+
+static INLINE void
+VThread_MonitorInit(Vcpuid vcpuID, int numVCPUs)
+{
+ /*
+ * Initialize vthreadMaxVCPUID first because
+ * VThread_VCPUIDToThreadID() depends on it.
+ */
+
+ vthreadMaxVCPUID = VTHREAD_VCPU0_ID + numVCPUs;
+ vthreadCurID = VThread_VCPUIDToThreadID(vcpuID);
+}
+
+#else // } {
+
+void VThread_SetNumVCPUs(int numVCPUs);
+VThreadID VThread_AllocID(void);
+Bool VThread_IsAllocatedID(VThreadID tid);
+void VThread_ReserveID(VThreadID tid);
+void VThread_FreeID(VThreadID tid);
+VThreadID VThread_CreateThread(void (*fn)(void *), void *data,
+ VThreadID tid, const char *name);
+void VThread_DestroyThread(VThreadID tid);
+Bool VThread_IsCurrentVThreadValid(void);
+void VThread_WaitThread(VThreadID tid);
+void VThread_SetPriorityLimits(int min, int max);
+void VThread_AdjustThreadPriority(VThreadID tid, int inc, int incHighest,
+ int incTimeCritical);
+Bool VThread_SetThreadPriority(VThreadID tid, int newPrio);
+uintptr_t VThread_GetApproxStackTop(VThreadID tid);
+
+void VThread_WatchThread(VThreadID tid, Bool watched);
+void VThread_WatchDog(void); // who let the ...
+void VThread_WatchDogPoll(void *clientData);
+
+void VThread_SetExitHook(void (*hook)(int loopCount));
+
+#ifdef _WIN32
+HANDLE VThread_GetHostThreadHandle(VThreadID tid);
+DWORD VThread_GetHostThreadID(VThreadID tid);
+#else
+int VThread_GetHostThreadPID(VThreadID tid);
+void VThread_SetIsInSignal(VThreadID tid, Bool isInSignal);
+#endif
+
+#endif // }
+
+#ifdef VTHREAD_RESOURCE_ACCOUNTING
+void VThread_DumpThreadRUsage(void);
+#else
+#define VThread_DumpThreadRUsage()
+#endif
+
+
+#endif // ifndef _VTHREAD_H_
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2006 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.
+ *
+ *********************************************************/
+
+/*
+ * vthreadBase.h --
+ *
+ * Subset of vthread defines that are used by libs that need to make
+ * vthread calls but don't actually do any vthreading. These libs
+ * can be linked against lib/nothread and will function correctly.
+ */
+
+#ifndef VTHREAD_BASE_H
+#define VTHREAD_BASE_H
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#if !defined VMM && !defined WIN32
+#define VTHREAD_USE_PTHREAD 1
+#endif
+
+
+/*
+ * Types
+ */
+
+typedef unsigned VThreadID;
+
+
+/*
+ * Constants
+ *
+ * VThread ID's are allocated this way:
+ * 0 -- VMX main thread
+ * 1 -- MKS
+ * 2 -- UI
+ * 3 -- other (main thread in simple apps)
+ * 4..3+VTHREAD_MAX_VCPUS -- VMX VCPU threads
+ * 4+VTHREAD_MAX_VCPUS.. -- additional dynamic threads
+ */
+
+#define VTHREAD_MAX_THREADS 96
+#define VTHREAD_MAX_VCPUS 32
+
+#define VTHREAD_INVALID_ID (~0u)
+
+#define VTHREAD_VMX_ID 0
+#define VTHREAD_MKS_ID 1
+#define VTHREAD_UI_ID 2
+#define VTHREAD_OTHER_ID 3
+#define VTHREAD_VCPU0_ID 4
+#define VTHREAD_ALLOCSTART_ID (VTHREAD_VCPU0_ID + VTHREAD_MAX_VCPUS)
+
+
+const char *VThread_CurName(void);
+
+#ifndef VMM
+VThreadID VThread_CurID(void);
+void VThread_Init(VThreadID tid, const char *name);
+VThreadID VThread_InitThread(VThreadID tid, const char *name);
+void NORETURN VThread_ExitThread(Bool clean);
+
+#ifdef _WIN32
+static INLINE Bool
+VThread_IsInSignal(void)
+{
+ /* Win32 does not worry about async-signal-safety. */
+ return FALSE;
+}
+#else
+Bool VThread_IsInSignal(void);
+#endif
+#endif
+
+
+#endif // VTHREAD_BASE_H
--- /dev/null
+################################################################################
+### Copyright 2009 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 = libLock.la
+
+libLock_la_SOURCES =
+libLock_la_SOURCES += ul.c
+libLock_la_SOURCES += ulCreate.c
+libLock_la_SOURCES += ulDestroy.c
+libLock_la_SOURCES += ulAcquire.c
+libLock_la_SOURCES += ulRelease.c
+libLock_la_SOURCES += ulTryAcquire.c
+libLock_la_SOURCES += ulIsLocked.c
+libLock_la_SOURCES += ulSingleton.c
+libLock_la_SOURCES += ulRWPosix.c
+
+AM_CFLAGS = @LIB_LOCK_CPPFLAGS@
+
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+
+#include "vmware.h"
+#include "str.h"
+#include "util.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+
+/*
+ * Return an invalid thread ID until lib/thread is initialized.
+ *
+ * XXX
+ *
+ * VThread_CurID cannot be called before VThread_Init is called; doing so
+ * causes assertion failures in some programs. This will go away when
+ * lib/nothread goes away - we'll assign "dense", rationalized VMware
+ * thread IDs without the distinction of lib/thread and lib/nothread.
+ */
+
+static VThreadID
+MXUserDummyCurID(void)
+{
+ return VTHREAD_INVALID_ID;
+}
+
+VThreadID (*MXUserThreadCurID)(void) = MXUserDummyCurID;
+
+void
+MXUserIDHack(void)
+{
+ MXUserThreadCurID = VThread_CurID;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserDumpAndPanic
+ *
+ * Dump a lock, print a message and die
+ *
+ * Results:
+ * A panic.
+ *
+ * Side effects:
+ * Manifold.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUserDumpAndPanic(MXRecLock *lock, // 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);
+
+ va_start(ap, fmt);
+ msg = Str_SafeVasprintf(NULL, fmt, ap);
+ va_end(ap);
+
+ Panic(msg);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserIsAllUnlocked --
+ *
+ * Is the lock currently completely unlocked?
+ *
+ * Results:
+ * The lock is acquired.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUserIsAllUnlocked(const MXUserRWLock *lock) // IN:
+{
+ uint32 i;
+
+ for (i = 0; i < VTHREAD_MAX_THREADS; i++) {
+ if (lock->lockTaken[i] != RW_UNLOCKED) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+
+#include "vmware.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_AcquireExclLock --
+ *
+ * An acquisition is made (lock is taken) on the specified exclusive lock.
+ *
+ * Results:
+ * The lock is acquired (locked).
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_AcquireExclLock(MXUserExclLock *lock) // IN/OUT:
+{
+ MXRecLockAcquire(&lock->basic, MXGetThreadID(), GetReturnAddress());
+
+ if (MXRecLockCount(&lock->basic) > 1) {
+ MXUserDumpAndPanic(&lock->basic,
+ "%s: Acquire on an acquired exclusive lock",
+ __FUNCTION__);
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_AcquireRecLock --
+ *
+ * An acquisition is made (lock is taken) on the specified recursive
+ * lock.
+ *
+ * Only the owner (thread) of a recursive lock may recurse on it.
+ *
+ * Results:
+ * The lock is acquired (locked).
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_AcquireRecLock(MXUserRecLock *lock) // IN/OUT:
+{
+ MXRecLockAcquire(&lock->basic, MXGetThreadID(), GetReturnAddress());
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+
+#include "vmware.h"
+#include "str.h"
+#include "util.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_CreateExclLock --
+ *
+ * Create an exclusive lock.
+ *
+ * Results:
+ * NULL Creation failed
+ * !NULL Creation succeeded
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+MXUserExclLock *
+MXUser_CreateExclLock(const char *userName, // IN:
+ MX_Rank rank) // IN:
+{
+ char *properName;
+ MXUserExclLock *lock;
+
+ lock = Util_SafeCalloc(1, sizeof(*lock));
+
+ if (userName == NULL) {
+ properName = Str_SafeAsprintf(NULL, "X-%p", GetReturnAddress());
+ } else {
+ properName = Util_SafeStrdup(userName);
+ }
+
+ if (!MXRecLockInit(&lock->basic, properName, rank)) {
+ free(lock);
+ free(properName);
+ lock = NULL;
+ }
+
+ return lock;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_CreateRecLock --
+ *
+ * Create a recursive lock.
+ *
+ * Only the owner (thread) of a recursive lock may recurse on it.
+ *
+ * Results:
+ * NULL Creation failed
+ * !NULL Creation succeeded
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+MXUserRecLock *
+MXUser_CreateRecLock(const char *userName, // IN:
+ MX_Rank rank) // IN:
+{
+ char *properName;
+ MXUserRecLock *lock;
+
+ lock = Util_SafeCalloc(1, sizeof(*lock));
+
+ if (userName == NULL) {
+ properName = Str_SafeAsprintf(NULL, "R-%p", GetReturnAddress());
+ } else {
+ properName = Util_SafeStrdup(userName);
+ }
+
+ if (MXRecLockInit(&lock->basic, properName, rank)) {
+ lock->vmmLock = NULL;
+ } else {
+ free(lock);
+ free(properName);
+ lock = NULL;
+ }
+
+ return lock;
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+#include "vmware.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_DestroyExclLock --
+ *
+ * Destroy an exclusive lock.
+ *
+ * Results:
+ * Lock is destroyed. Don't use the pointer again.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_DestroyExclLock(MXUserExclLock *lock) // IN:
+{
+ if (lock != NULL) {
+ if (MXRecLockCount(&lock->basic) > 0) {
+ MXUserDumpAndPanic(&lock->basic,
+ "%s: Destroy of an acquired exclusive lock",
+ __FUNCTION__);
+ }
+
+ MXRecLockDestroy(&lock->basic);
+ free(lock);
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_DestroyRecLock --
+ *
+ * Destroy a recursive lock.
+ *
+ * Results:
+ * Lock is destroyed. Don't use the pointer again.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_DestroyRecLock(MXUserRecLock *lock) // IN:
+{
+ if (lock != NULL) {
+ if (MXRecLockCount(&lock->basic) > 0) {
+ MXUserDumpAndPanic(&lock->basic,
+ "%s: Destroy of an acquired recursive lock",
+ __FUNCTION__);
+ }
+
+ MXRecLockDestroy(&lock->basic);
+ free(lock);
+ }
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+#ifndef _ULINT_H_
+#define _ULINT_H_
+
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32)
+typedef DWORD MXThreadID;
+#else
+#include <pthread.h>
+#include <errno.h>
+typedef pthread_t MXThreadID;
+#endif
+
+#include "vm_basic_types.h"
+#include "vthread.h"
+
+/* XXX hack until thread/nothread IDs are rationalized */
+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;
+#else
+ pthread_mutex_t lockObject;
+#endif
+} MXRecLock;
+
+
+/*
+ * Environment specific implementations of portable recursive locks.
+ *
+ * A recursive lock is used throughput the MXUser locks because:
+ * - it can be used recursively for recursive locks
+ * - exclusive (non-recursive) locks catch the recursion and panic
+ * rather than deadlock.
+ *
+ * There are 7 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)
+ *
+ * Windows has a native recursive lock, the CRITICAL_SECTION. POSIXen,
+ * unfortunately, do not ensure access to such a facility. The recursive
+ * attribute of pthread_mutex_t is not implemented in all environments so
+ * we create a recursive implementation using an exclusive pthread_mutex_t
+ * and a few lines of code (most of which we need to do anyway).
+ */
+
+#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:
+{
+ /* http://msdn.microsoft.com/en-us/library/ms682530(VS.85).aspx */
+ /* magic number - allocate resources immediately; spin 0x400 times */
+ return InitializeCriticalSectionAndSpinCount(lockObject, 0x80000400) != 0;
+}
+
+
+static INLINE void
+MXRecLockDestroy(MXRecLock *lock) // IN/OUT:
+{
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ DeleteCriticalSection(&lock->lockObject);
+ free((void *) lock->lockHeader.lockName);
+}
+
+
+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));
+
+ if (lock->lockHeader.lockCount == 0) {
+ ASSERT(lock->lockHeader.lockVThreadID == VTHREAD_INVALID_ID);
+ lock->lockHeader.lockOwner = self;
+ lock->lockHeader.lockCaller = location;
+ lock->lockHeader.lockVThreadID = (*MXUserThreadCurID)();
+
+ }
+
+ lock->lockHeader.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)();
+ }
+
+ lock->lockHeader.lockCount++;
+ }
+
+ return success;
+}
+
+
+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));
+
+ lock->lockHeader.lockCount--;
+
+ if (lock->lockHeader.lockCount == 0) {
+ lock->lockHeader.lockCaller = NULL;
+ lock->lockHeader.lockVThreadID = VTHREAD_INVALID_ID;
+ }
+
+ 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:
+{
+ return pthread_mutex_init(lockObject, NULL) == 0;
+}
+
+
+static INLINE void
+MXRecLockDestroy(MXRecLock *lock) // 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 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));
+
+ lock->lockHeader.lockCount++;
+ } else {
+ int err;
+
+ err = pthread_mutex_lock(&lock->lockObject);
+
+ if (vmx86_debug && (err != 0)) {
+ Panic("%s: pthread_mutex_lock returned %d\n", __FUNCTION__, err);
+ }
+
+ ASSERT(lock->lockHeader.lockCount == 0);
+ ASSERT(lock->lockHeader.lockVThreadID == VTHREAD_INVALID_ID);
+
+ lock->lockHeader.lockOwner = self;
+ lock->lockHeader.lockCaller = location;
+ lock->lockHeader.lockCount = 1;
+ lock->lockHeader.lockVThreadID = (*MXUserThreadCurID)();
+ }
+}
+
+
+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)();
+ }
+
+ lock->lockHeader.lockCount++;
+
+ acquired = TRUE;
+ } else {
+ if (vmx86_debug && (err != EBUSY)) {
+ Panic("%s: pthread_mutex_trylock returned %d\n", __FUNCTION__, err);
+ }
+
+ acquired = FALSE;
+ }
+
+ return acquired;
+}
+
+
+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));
+
+ lock->lockHeader.lockCount--;
+
+ if (lock->lockHeader.lockCount == 0) {
+ int err;
+
+ lock->lockHeader.lockCaller = NULL;
+ lock->lockHeader.lockVThreadID = VTHREAD_INVALID_ID;
+
+ err = pthread_mutex_unlock(&lock->lockObject);
+
+ if (vmx86_debug && (err != 0)) {
+ Panic("%s: pthread_mutex_unlock returned %d\n", __FUNCTION__, err);
+ }
+ }
+}
+#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:
+{
+ ASSERT(rank == RANK_UNRANKED); // NOT FOR LONG
+ ASSERT(userName != NULL);
+
+ if (!MXRecLockObjectInit(&lock->lockObject)) {
+ return FALSE;
+ }
+
+ MXRecLockInitHeader(lock, userName, rank);
+
+ return TRUE;
+}
+
+
+static INLINE uint32
+MXRecLockCount(const MXRecLock *lock) // IN:
+{
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ return lock->lockHeader.lockCount;
+}
+
+
+static INLINE const char *
+MXRecLockName(const MXRecLock *lock) // IN:
+{
+ ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
+
+ return lock->lockHeader.lockName;
+}
+
+
+static INLINE uint32
+MXRecLockSignature(const MXRecLock *lock) // IN:
+{
+ return lock->lockHeader.lockSignature;
+}
+
+/*
+ * The internal lock types
+ */
+
+struct MXUserExclLock
+{
+ MXRecLock basic;
+};
+
+struct MXUserRecLock
+{
+ MXRecLock basic;
+
+ /*
+ * This is the MX recursive lock override pointer. This pointer is NULL
+ * for standard MXUser recursive locks. It will be not NULL when a
+ * special "bind an MXUser recursive lock to an MX recursive lock"
+ * function is called. The binding function will come along in the near
+ * future. This will make things like Poll able to user MXUser locks.
+ *
+ * NULL use MXRecLock within this structure
+ * !NULL use pointed to MX recursive lock
+ */
+
+ void *vmmLock;
+};
+
+struct MXUserRWLock
+{
+ MXRecLock lockRecursive; // Used as a header or maybe for real
+
+ uint8 lockTaken[VTHREAD_MAX_THREADS];
+
+#if defined(_WIN32)
+ SRWLOCK lockReadWrite;
+#else
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ pthread_rwlock_t lockObject;
+#endif
+#endif
+};
+
+/*
+ * Internal functions
+ */
+
+#define RW_UNLOCKED 0
+#define RW_LOCKED_FOR_READ 1
+#define RW_LOCKED_FOR_WRITE 2
+
+Bool MXUserIsAllUnlocked(const MXUserRWLock *lock);
+
+void MXUserDumpAndPanic(MXRecLock *lock,
+ const char *fmt,
+ ...);
+#endif
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+#include "vmware.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_IsLockedByCurThreadExclLock --
+ *
+ * Is an exclusive lock held by the calling thread?
+ *
+ * Results:
+ * TRUE Yes
+ * FALSE No
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_IsLockedByCurThreadExclLock(const MXUserExclLock *lock) // IN:
+{
+ return MXRecLockIsOwner(&lock->basic);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_IsLockedByCurThreadRecLock --
+ *
+ * Is a recursive lock held by the calling thread?
+ *
+ * Results:
+ * TRUE Yes
+ * FALSE No
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_IsLockedByCurThreadRecLock(const MXUserRecLock *lock) // IN:
+{
+ return MXRecLockIsOwner(&lock->basic);
+}
+
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+#include <errno.h>
+
+#include "vmware.h"
+#include "str.h"
+#include "util.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_CreateRWLock --
+ *
+ * Create a read-write lock.
+ *
+ * Results:
+ * A pointer to a read-write lock.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+MXUserRWLock *
+MXUser_CreateRWLock(const char *userName, // IN:
+ MX_Rank rank) // IN:
+{
+ char *properName;
+ MXUserRWLock *lock;
+
+ ASSERT(rank == RANK_UNRANKED); // NOT FOR LONG
+
+ lock = Util_SafeCalloc(1, sizeof(*lock));
+
+ if (userName == NULL) {
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress());
+#else
+ /* emulated */
+ properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress());
+#endif
+ } else {
+ properName = Util_SafeStrdup(userName);
+ }
+
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ if (pthread_rwlock_init(&lock->lockObject, 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)) {
+ free((void *) properName);
+ free(lock);
+ lock = NULL;
+ }
+
+ return lock;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_AcquireForRead --
+ *
+ * Acquire a read-write lock for read-shared access.
+ *
+ * Results:
+ * The lock is acquired.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_AcquireForRead(MXUserRWLock *lock) // IN/OUT:
+{
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ int err;
+#endif
+
+ VThreadID self = VThread_CurID();
+
+ ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ err = pthread_rwlock_rdlock(&lock->lockObject);
+
+ if (err == 0) {
+ if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
+ MXUserDumpAndPanic(&lock->lockRecursive,
+ "%s: AcquireForRead after AcquireForRead",
+ __FUNCTION__);
+ }
+ } else {
+ MXUserDumpAndPanic(&lock->lockRecursive, "%s: %s",
+ (err == EDEADLK) ? "Deadlock detected (%d)" :
+ "Internal error (%d)",
+ __FUNCTION__, err);
+ }
+#else
+ MXRecLockAcquire(&lock->lockRecursive, MXGetThreadID(), GetReturnAddress());
+
+ if (lock->lockTaken[self] != RW_UNLOCKED) {
+ if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
+ MXUserDumpAndPanic(&lock->lockRecursive,
+ "%s: AcquireForRead after AcquireForRead"
+ __FUNCTION__, self);
+ } else {
+ MXUserDumpAndPanic(&lock->lockRecursive,
+ "%s: AcquireForRead after AcquireForWrite"
+ __FUNCTION__, self);
+ }
+ }
+
+ ASSERT(MXUserIsAllUnlocked(lock));
+#endif
+
+ lock->lockTaken[self] = RW_LOCKED_FOR_READ;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_AcquireForWrite --
+ *
+ * Acquire a read-write lock for write-exclusive access.
+ *
+ * Results:
+ * The lock is acquired.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_AcquireForWrite(MXUserRWLock *lock) // IN/OUT:
+{
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ int err;
+#endif
+
+ VThreadID self = VThread_CurID();
+
+ ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ err = pthread_rwlock_wrlock(&lock->lockObject);
+
+ if (err != 0) {
+ MXUserDumpAndPanic(&lock->lockRecursive, "%s: %s",
+ (err == EDEADLK) ? "Deadlock detected (%d)" :
+ "Internal error (%d)",
+ __FUNCTION__, err);
+ }
+#else
+ MXRecLockAcquire(&lock->lockRecursive, MXGetThreadID(), GetReturnAddress());
+
+ if (lock->lockTaken[self] != RW_UNLOCKED) {
+ if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
+ MXUserDumpAndPanic(&lock->lockRecursive,
+ "%s: AcquireForRead after AcquireForWrite"
+ __FUNCTION__);
+ } else {
+ MXUserDumpAndPanic(&lock->lockRecursive,
+ "%s: AcquireForWrite after AcquireForWrite"
+ __FUNCTION__);
+ }
+ }
+#endif
+
+ ASSERT(MXUserIsAllUnlocked(lock));
+
+ lock->lockTaken[self] = RW_LOCKED_FOR_WRITE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_ReleaseRWLock --
+ *
+ * A read-write lock is released (unlocked).
+ *
+ * Results:
+ * The lock is released (unlocked).
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_ReleaseRWLock(MXUserRWLock *lock) // IN/OUT:
+{
+ VThreadID self = VThread_CurID();
+ uint8 myState = lock->lockTaken[self];
+
+ ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+
+ if (myState == RW_UNLOCKED) {
+ MXUserDumpAndPanic(&lock->lockRecursive,
+ "%s: Release of read-lock not by owner (%d)",
+ __FUNCTION__, self);
+ }
+
+ lock->lockTaken[self] = RW_UNLOCKED;
+
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ if (vmx86_debug && (myState == RW_LOCKED_FOR_WRITE)) {
+ ASSERT(MXUserIsAllUnlocked(lock));
+ }
+
+ pthread_rwlock_unlock(&lock->lockObject);
+#else
+ ASSERT(MXUserIsAllUnlocked(lock));
+ MXRecLockRelease(&lock->lockRecursive);
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_DestroyRWLock --
+ *
+ * Destroy a read-write lock.
+ *
+ * Results:
+ * The lock is destroyed. Don't try to use the pointer again.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_DestroyRWLock(MXUserRWLock *lock) // IN:
+{
+ if (lock != NULL) {
+ ASSERT(MXRecLockSignature(&lock->lockRecursive) == USERLOCK_SIGNATURE);
+
+ if (!MXUserIsAllUnlocked(lock)) {
+ MXUserDumpAndPanic(&lock->lockRecursive,
+ "%s: Destroy on read-lock while still acquired",
+ __FUNCTION__);
+ }
+
+#if defined(PTHREAD_RWLOCK_INITIALIZER)
+ pthread_rwlock_destroy(&lock->lockObject);
+#endif
+
+ MXRecLockDestroy(&lock->lockRecursive);
+ free(lock);
+ }
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+#include "vmware.h"
+#include "userlock.h"
+#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);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_ReleaseExclLock --
+ *
+ * Release (unlock) an exclusive lock.
+ *
+ * Results:
+ * The lock is released.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_ReleaseExclLock(MXUserExclLock *lock) // IN/OUT:
+{
+ MXUserReleaseExclLock(&lock->basic, "exclusive");
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_ReleaseRecLock --
+ *
+ * Release (unlock) a recursive lock.
+ *
+ * Results:
+ * The lock is released.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUser_ReleaseRecLock(MXUserRecLock *lock) // IN/OUT:
+{
+ MXUserReleaseExclLock(&lock->basic, "recursive");
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+#include "vmware.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_CreateSingletonExclLock --
+ *
+ * Ensures that the specified backing object (Atomic_Ptr) contains a
+ * exclusive lock. This is useful for modules that need to protect
+ * something with a lock but don't have an existing Init() entry point
+ * where a lock can be created.
+ *
+ * Results:
+ * A pointer to the requested lock.
+ *
+ * Side effects:
+ * Generally the lock's resources are intentionally leaked (by design).
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+MXUserExclLock *
+MXUser_CreateSingletonExclLock(Atomic_Ptr *lockStorage, // IN/OUT:
+ const char *name, // IN:
+ MX_Rank rank) // IN:
+{
+ MXUserExclLock *lock = (MXUserExclLock *) Atomic_ReadPtr(lockStorage);
+
+ if (UNLIKELY(lock == NULL)) {
+ MXUserExclLock *before;
+
+ lock = MXUser_CreateExclLock(name, rank);
+
+ before = (MXUserExclLock *) Atomic_ReadIfEqualWritePtr(lockStorage, NULL,
+ (void *) lock);
+
+ if (before) {
+ MXUser_DestroyExclLock(lock);
+
+ lock = before;
+ }
+ }
+
+ return lock;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_CreateSingletonRecLock --
+ *
+ * Ensures that the specified backing object (Atomic_Ptr) contains a
+ * recursive lock. This is useful for modules that need to protect
+ * something with a lock but don't have an existing Init() entry point
+ * where a lock can be created.
+ *
+ * Results:
+ * A pointer to the requested lock.
+ *
+ * Side effects:
+ * Generally the lock's resources are intentionally leaked (by design).
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+MXUserRecLock *
+MXUser_CreateSingletonRecLock(Atomic_Ptr *lockStorage, // IN/OUT:
+ const char *name, // IN:
+ MX_Rank rank) // IN:
+{
+ MXUserRecLock *lock = (MXUserRecLock *) Atomic_ReadPtr(lockStorage);
+
+ if (UNLIKELY(lock == NULL)) {
+ MXUserRecLock *before;
+
+ lock = MXUser_CreateRecLock(name, rank);
+
+ before = (MXUserRecLock *) Atomic_ReadIfEqualWritePtr(lockStorage, NULL,
+ (void *) lock);
+
+ if (before) {
+ MXUser_DestroyRecLock(lock);
+
+ lock = before;
+ }
+ }
+
+ return lock;
+}
+
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 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.
+ *
+ *********************************************************/
+
+
+#include "vmware.h"
+#include "userlock.h"
+#include "ulInt.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_TryAcquireExclLock --
+ *
+ * An attempt is made to conditionally acquire (lock) an exclusive lock.
+ *
+ * Results:
+ * TRUE Acquired (locked)
+ * FALSE Not acquired
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_TryAcquireExclLock(MXUserExclLock *lock) // IN/OUT:
+{
+ Bool success;
+
+ success = MXRecLockTryAcquire(&lock->basic, MXGetThreadID(),
+ GetReturnAddress());
+
+ if (success && (MXRecLockCount(&lock->basic) > 1)) {
+ MXUserDumpAndPanic(&lock->basic,
+ "%s: Acquire on an acquired exclusive lock",
+ __FUNCTION__);
+ }
+
+ return success;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_TryAcquireRecLock --
+ *
+ * An attempt is made to conditionally acquire (lock) a recursive lock.
+ *
+ * Only the owner (thread) of a recursive lock may recurse on it.
+ *
+ * Results:
+ * TRUE Acquired (locked)
+ * FALSE Not acquired
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_TryAcquireRecLock(MXUserRecLock *lock) // IN/OUT:
+{
+ return MXRecLockTryAcquire(&lock->basic, MXGetThreadID(),
+ GetReturnAddress());
+}
--- /dev/null
+################################################################################
+### Copyright 2009 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 = libNothread.la
+
+libNothread_la_SOURCES =
+libNothread_la_SOURCES += vthreadUL.c
+
+AM_CFLAGS = @LIB_NOTHREAD_CPPFLAGS@
+
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2002 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.
+ *
+ *********************************************************/
+
+/*
+ * vthreadUL.c --
+ *
+ * Thread management without actually having threads
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(_WIN32)
+#include <windows.h>
+#elif defined(__APPLE__) || defined(__GLIBC__)
+#include <pthread.h>
+#endif
+
+#include "vmware.h"
+#include "vthreadBase.h"
+#include "str.h"
+
+
+/*
+ * Local data
+ *
+ * Initialize thread ID and name so VThread_Init() is optional.
+ */
+
+static VThreadID vthreadCurID = VTHREAD_OTHER_ID;
+static uintptr_t vthreadHostThreadID = 0;
+static Bool vthreadIsInSignal = FALSE;
+
+#if VTHREAD_OTHER_ID != 3
+#error "VTHREAD_OTHER_ID is not 3"
+#endif
+
+static char vthreadNames[VTHREAD_MAX_THREADS][32] = {
+ "",
+ "",
+ "",
+ "app"
+};
+
+/*
+ * Symbol that needs to be available for lib/lock.
+ */
+
+VThreadID vthreadMaxVCPUID = VTHREAD_VCPU0_ID;
+
+/*
+ * Local functions
+ */
+
+// nothing
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThreadHostThreadID --
+ *
+ * Determine some sort of OS-specific unique threadID.
+ *
+ * Nominally, lib/nothread is single-threaded; HostThreadID
+ * would help us detect multithreaded violators.
+ *
+ * Results:
+ * A per-thread unique uintptr_t.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static uintptr_t
+VThreadHostThreadID(void)
+{
+#if defined(_WIN32)
+ return GetCurrentThreadId();
+#elif defined(__GLIBC__)
+ return pthread_self();
+#elif defined(__APPLE__)
+ return (uintptr_t)(void*)pthread_self();
+#else
+ return -1;
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThread_Init --
+ *
+ * Module and main thread initialization.
+ *
+ * This should be called by the main thread early.
+ *
+ * See VThread_InitThread.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Set initial state.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+VThread_Init(VThreadID id, // IN: this thread's ID
+ const char *name) // IN: this thread's name
+{
+ if (id == VTHREAD_INVALID_ID) {
+ id = VTHREAD_OTHER_ID;
+ }
+ ASSERT(id >= 0 && id < VTHREAD_VCPU0_ID);
+
+ vthreadCurID = id;
+
+ if (vthreadHostThreadID == 0) {
+ vthreadHostThreadID = VThreadHostThreadID();
+ }
+
+ ASSERT(name != NULL);
+ ASSERT(vthreadNames[id][ARRAYSIZE(vthreadNames[id]) - 1] == '\0');
+ strncpy(vthreadNames[id], name, ARRAYSIZE(vthreadNames[id]) - 1);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThread_InitThread --
+ *
+ * Initialize a thread.
+ *
+ * This should be called by threads started outside our control.
+ * Threads started by VThread_CreateThread need to do nothing.
+ *
+ * Results:
+ * The thread ID.
+ *
+ * Side effects:
+ * Set initial state.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+VThreadID
+VThread_InitThread(VThreadID id, // IN: this thread's ID
+ const char *name) // IN: this thread's name
+{
+ if (id == VTHREAD_INVALID_ID) {
+ /*
+ * XXX This emulates some old, broken expectations of callers
+ * of Thread_Init(VTHREAD_OTHER_ID) in third-party threads
+ * that can also link with either lib/thread or lib/nothread.
+ * The calls have become VThread_InitThread(VTHREAD_INVALID_ID),
+ * and should behave in the same broken way here and correctly
+ * in lib/thread.
+ */
+
+ id = VTHREAD_OTHER_ID;
+ } else {
+ ASSERT(id >= VTHREAD_ALLOCSTART_ID && id < VTHREAD_MAX_THREADS);
+ }
+
+ vthreadCurID = id;
+
+ if (vthreadHostThreadID == 0) {
+ vthreadHostThreadID = VThreadHostThreadID();
+ }
+
+ if (name == NULL) {
+ Str_Snprintf(vthreadNames[id], ARRAYSIZE(vthreadNames[id]),
+ "vthread-%d", id);
+ } else {
+ ASSERT(vthreadNames[id][ARRAYSIZE(vthreadNames[id]) - 1] == '\0');
+ strncpy(vthreadNames[id], name, ARRAYSIZE(vthreadNames[id]) - 1);
+ }
+
+ return id;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThread_CurID --
+ *
+ * Get the current thread ID.
+ *
+ * Results:
+ * Thread ID.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+VThreadID
+VThread_CurID(void)
+{
+ ASSERT(vthreadCurID < VTHREAD_MAX_THREADS);
+
+ return vthreadCurID;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThread_CurName --
+ *
+ * Get the current thread name.
+ *
+ * Results:
+ * The current thread name.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+const char *
+VThread_CurName(void)
+{
+ uintptr_t hostTID = VThreadHostThreadID();
+
+ if (LIKELY(hostTID == vthreadHostThreadID)) {
+ return vthreadNames[vthreadCurID];
+ } else {
+ static char name[48];
+
+ /*
+ * There were multiple threads. Do our best,
+ * but use a static buffer because clients shouldn't be
+ * using us anyway if they are multithreaded.
+ *
+ * XXX: in the future, we should wean people off
+ * lib/nothread by putting an ASSERT here!
+ */
+
+ snprintf(name, sizeof name, "%s-%"FMTPD"u",
+ vthreadNames[vthreadCurID], hostTID);
+ name[sizeof name - 1] = '\0';
+
+ return name;
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VThread_ExitThread --
+ *
+ * Exit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bye bye.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+VThread_ExitThread(Bool clean) // IN:
+{
+ /*
+ * On Linux, we can't possibly have threads, since we're not
+ * supposed to link with libpthread.
+ * So plain exit() will (and has to) do.
+ *
+ * On Windows, it's unclear what we should do here.
+ * There may or may not be threads, but this module doesn't know
+ * either way. It depends on the caller's intent.
+ *
+ * The very first caller of this function was an old
+ * WS UI. Since that was a process on Linux
+ * and a thread on Windows, we acted accordingly.
+ * It still seems to be a good idea.
+ *
+ * -- edward
+ */
+
+#if defined(_WIN32)
+ ExitThread(clean ? 0 : 1);
+#else
+ exit(clean ? 0 : 1);
+#endif
+
+ NOT_REACHED();
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VThread_SetIsInSignal --
+ *
+ * Set the 'is in signal' state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes internal state.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+VThread_SetIsInSignal(VThreadID tid, // IN:
+ Bool isInSignal) // IN:
+{
+ vthreadIsInSignal = isInSignal;
+}
+
+
+#if !defined(_WIN32)
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VThread_IsInSignal --
+ *
+ * Return the 'is in signal' state.
+ *
+ * Results:
+ * Returns last value passed to VThread_SetIsInSignal.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+VThread_IsInSignal(void)
+{
+ return vthreadIsInSignal;
+}
+#endif
}
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncMutex_CreateSingleton --
- *
- * Creates and returns a mutex backed by the specified storage in a
- * thread-safe manner. This is useful for modules that need to
- * protect something with a lock but don't have an existing Init()
- * entry point where a lock can be created.
- *
- * Results:
- * A pointer to the mutex. Don't destroy it.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-SyncMutex *
-SyncMutex_CreateSingleton(Atomic_Ptr *lckStorage) // IN
-{
- SyncMutex *before, *lck;
-
- /* Check if we've created the lock already. */
- lck = (SyncMutex *) Atomic_ReadPtr(lckStorage);
-
- if (UNLIKELY(NULL == lck)) {
- /* We haven't, create it. */
- lck = (SyncMutex *) Util_SafeMalloc(sizeof *lck);
- SyncMutex_Init(lck, NULL);
-
- /*
- * We have successfully created the lock, save it.
- */
-
- before = (SyncMutex *) Atomic_ReadIfEqualWritePtr(lckStorage, NULL, lck);
-
- if (before) {
- /* We raced and lost, but it's all cool. */
- SyncMutex_Destroy(lck);
- free(lck);
- lck = before;
- }
- }
-
- return lck;
-}
-
-
/*
*-----------------------------------------------------------------------------
*
int *blockedWnd, // IN
DesktopSwitchCallbackManager *desktopSwitchCallbackMgr) // IN
{
+ /*
+ * If no preferred color is in the config file then use a light gray tone,
+ * the value is stored as xBGR.
+ */
+ int desktopColor = /* red */ 0xdc |
+ /* green */ 0xdc << 8 |
+ /* blue */ 0xdc << 16;
Debug("Unity_Init\n");
/*
unity.forceEnable = GuestApp_GetDictEntryBool(conf, "unity.forceEnable");
unity.isEnabled = FALSE;
+ GuestApp_GetDictEntryInt(conf, "unity.desktop.backgroundColor", &desktopColor);
+ UnityPlatformSetConfigDesktopColor(unity.up, desktopColor);
unity.virtDesktopArray.desktopCount = 0;
}
void UnityPlatformDoUpdate(UnityPlatform *up, Bool incremental);
+void UnityPlatformSetConfigDesktopColor(UnityPlatform *up, int desktopColor);
+
/* Functions implemented in unity.c for use by the platform-specific code. */
void UnityGetUpdateCommon(int flags, DynBuf *buf);
Bool UnityUpdateChannelInit(UnityUpdateChannel *updateChannel);
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UnityPlatformSetConfigDesktopColor --
+ *
+ * Set the preferred desktop background color for use when in Unity Mode.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+UnityPlatformSetConfigDesktopColor(UnityPlatform *up, int desktopColor)
+{
+ ASSERT(up);
+}
+
+
/*
******************************************************************************
* Begin file-scope functions.
#include "vm_version.h"
#include "random.h"
#include "hostinfo.h"
-#include "syncMutex.h"
+#include "userlock.h"
#include "escape.h"
#include "unicodeOperations.h"
#include "err.h"
char *baseTmpDir = NULL;
char *userName = NULL;
uid_t userId;
- SyncMutex *lck;
+ MXUserExclLock *lck;
userId = geteuid();
/* Get and take lock for our safe dir. */
- lck = SyncMutex_CreateSingleton(&lckStorage);
- SyncMutex_Lock(lck);
+ lck = MXUser_CreateSingletonExclLock(&lckStorage, __FUNCTION__,
+ RANK_UNRANKED);
+ ASSERT_NOT_IMPLEMENTED(lck != NULL);
+
+ MXUser_AcquireExclLock(lck);
/*
* Check if we've created a temporary dir already and if it is
}
exit:
- SyncMutex_Unlock(lck);
+ MXUser_ReleaseExclLock(lck);
free(baseTmpDir);
free(userName);
libvmtools_la_LIBADD += ../lib/guestRpc/libGuestRpc.la
libvmtools_la_LIBADD += ../lib/hgfs/libHgfs.la
libvmtools_la_LIBADD += ../lib/message/libMessage.la
-libvmtools_la_LIBADD += ../lib/misc/libMisc.la
libvmtools_la_LIBADD += ../lib/netUtil/libNetUtil.la
libvmtools_la_LIBADD += ../lib/panic/libPanic.la
libvmtools_la_LIBADD += ../lib/procMgr/libProcMgr.la
libvmtools_la_LIBADD += ../lib/vmCheck/libVmCheck.la
libvmtools_la_LIBADD += ../lib/vmSignal/libVmSignal.la
libvmtools_la_LIBADD += ../lib/wiper/libWiper.la
+libvmtools_la_LIBADD += ../lib/lock/libLock.la
+libvmtools_la_LIBADD += ../lib/nothread/libNothread.la
+libvmtools_la_LIBADD += ../lib/misc/libMisc.la
libvmtools_la_LIBADD += @LIBVMTOOLS_LIBADD@
libvmtools_la_LIBADD += @GLIB2_LIBS@
libvmtools_la_LIBADD += @ICU_LIBS@
libvmtools_la_LDFLAGS =
# We require GCC, so we're fine passing compiler-specific flags.
libvmtools_la_LDFLAGS += -Wl,-z,defs
-# Needed for OS's that don't link shared libraries against libc by default, e.g. FreeBSD
+# Needed for OS's that don't link shared libraries against libc by
+#default, e.g. FreeBSD
libvmtools_la_LDFLAGS += -Wl,-lc
struct Vmxnet_Private *lp = netdev_priv(dev);
volatile u16 *mcast_table = (u16 *)lp->dd->LADRF;
struct dev_mc_list *dmi = dev->mc_list;
- char *addrs;
+ u8 *addrs;
int i, j, bit, byte;
u32 crc, poly = CRC_POLYNOMIAL_LE;
struct vmxnet3_adapter *adapter = compat_netdev_priv(netdev);
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- vmxnet3_write_mac_addr(adapter, addr->sa_data);
+ vmxnet3_write_mac_addr(adapter, netdev->dev_addr);
return 0;
}
#define NPA_PLUGIN_NUMPAGES 64
#define NPA_MEMIO_NUMPAGES 32
-#define NPA_CMD_LOAD_SUCCESS 1
-#define NPA_DEVICE_INFO_LEN 8
+#define VMXNET3_NPA_CMD_SUCCESS 0
+#define VMXNET3_NPA_CMD_FAILURE 1
+#define VMXNET3_PLUGIN_INFO_LEN 32
+// XXX: unify the definitions
/* these structure are versioned using the vmxnet3 version */
NPA_PluginPages pluginPages;
NPA_MemioPages memioPages;
uint64 entryVA; // address of entry function in the plugin
- uint32 deviceInfo[NPA_DEVICE_INFO_LEN]; // opaque data returned by PF driver
+ uint32 deviceInfo[VMXNET3_PLUGIN_INFO_LEN]; // opaque data returned by PF driver
}
#include "vmware_pack_end.h"
NPA_PluginConf;
/* vmkernel and device backend shared definitions */
-#define VMXNET3_PLUGIN_NAME_LEN 256
+#define VMXNET3_PLUGIN_NAME_LEN 256
+#define NPA_MEMIO_REGIONS_MAX 6
typedef uint32 VF_ID;
typedef struct Vmxnet3_VFInfo {
char pluginName[VMXNET3_PLUGIN_NAME_LEN];
- uint32 deviceInfo[NPA_DEVICE_INFO_LEN]; // opaque data returned by PF driver
+ uint32 deviceInfo[VMXNET3_PLUGIN_INFO_LEN]; // opaque data returned by PF driver
MA memioAddr;
uint32 memioLen;
} Vmxnet3_VFInfo;
VMXNET3_CMD_UPDATE_IML,
VMXNET3_CMD_UPDATE_PMCFG,
VMXNET3_CMD_UPDATE_FEATURE,
+ VMXNET3_CMD_STOP_EMULATION,
VMXNET3_CMD_LOAD_PLUGIN,
+ VMXNET3_CMD_ACTIVATE_VF,
VMXNET3_CMD_FIRST_GET = 0xF00D0000,
VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
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
COMMON += ../lib/panicDefault/libPanicDefault.la
COMMON += ../lib/panic/libPanic.la
vmware_user_LDADD += ../lib/message/libMessage.la
vmware_user_LDADD += ../lib/unicode/libUnicode.la
vmware_user_LDADD += ../lib/auth/libAuth.la
-vmware_user_LDADD += ../lib/misc/libMisc.la
vmware_user_LDADD += ../lib/procMgr/libProcMgr.la
vmware_user_LDADD += ../lib/panicDefault/libPanicDefault.la
vmware_user_LDADD += ../lib/panic/libPanic.la
vmware_user_LDADD += ../lib/raster/libRaster.la
vmware_user_LDADD += ../lib/region/libRegion.la
endif
+
vmware_user_LDADD += -lcrypt
vmware_user_LDADD += -lstdc++
if USE_SLASH_PROC
vmware_user_LDADD += -lgcc_s
vmware_user_LDADD += ../lib/slashProc/libSlashProc.la
endif
+
+vmware_user_LDADD += ../lib/lock/libLock.la
+vmware_user_LDADD += ../lib/nothread/libNothread.la
+vmware_user_LDADD += ../lib/misc/libMisc.la
+
vmware_user_LDADD += @GTK_LIBS@
if HAVE_GTKMM
vmware_user_LDADD += @GTKMM_LIBS@