From: VMware, Inc <> Date: Thu, 17 Dec 2009 22:50:00 +0000 (-0800) Subject: Internal branch sync. Included in this change: X-Git-Tag: 2009.12.16-217847~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fc38795548d1741bcaee29ee2a98fd274c7341ea;p=thirdparty%2Fopen-vm-tools.git Internal branch sync. Included in this change: . 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 --- diff --git a/open-vm-tools/configure.ac b/open-vm-tools/configure.ac index a72ee7a46..f6456c646 100644 --- a/open-vm-tools/configure.ac +++ b/open-vm-tools/configure.ac @@ -1182,7 +1182,9 @@ AC_SUBST([LIB_AUTH_CPPFLAGS]) 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]) @@ -1225,9 +1227,11 @@ AC_CONFIG_FILES([ \ 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 \ diff --git a/open-vm-tools/lib/Makefile.am b/open-vm-tools/lib/Makefile.am index 486861810..974c77cf3 100644 --- a/open-vm-tools/lib/Makefile.am +++ b/open-vm-tools/lib/Makefile.am @@ -50,9 +50,11 @@ if ENABLE_UNITY SUBDIRS += image endif SUBDIRS += impersonate +SUBDIRS += lock SUBDIRS += message SUBDIRS += misc SUBDIRS += netUtil +SUBDIRS += nothread SUBDIRS += panic SUBDIRS += panicDefault SUBDIRS += printer diff --git a/open-vm-tools/lib/hgfsServer/hgfsServer.c b/open-vm-tools/lib/hgfsServer/hgfsServer.c index eca785247..fa2bd7b4f 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServer.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServer.c @@ -30,7 +30,7 @@ #include "file.h" #include "util.h" #include "wiper.h" -#include "syncMutex.h" +#include "userlock.h" #include "hgfsDirNotify.h" #if defined(_WIN32) @@ -495,7 +495,7 @@ HgfsHandle2FileDesc(HgfsHandle handle, // IN: Hgfs file handle Bool found = FALSE; HgfsFileNode *fileNode = NULL; - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); fileNode = HgfsHandle2FileNode(handle, session); if (fileNode == NULL) { goto exit; @@ -508,7 +508,7 @@ HgfsHandle2FileDesc(HgfsHandle handle, // IN: Hgfs file handle found = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); return found; } @@ -540,7 +540,7 @@ HgfsHandle2AppendFlag(HgfsHandle handle, // IN: Hgfs file handle Bool found = FALSE; HgfsFileNode *fileNode = NULL; - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); fileNode = HgfsHandle2FileNode(handle, session); if (fileNode == NULL) { goto exit; @@ -550,7 +550,7 @@ HgfsHandle2AppendFlag(HgfsHandle handle, // IN: Hgfs file handle found = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); return found; } @@ -584,7 +584,7 @@ HgfsHandle2LocalId(HgfsHandle handle, // IN: Hgfs file handle ASSERT(localId); - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); fileNode = HgfsHandle2FileNode(handle, session); if (fileNode == NULL) { goto exit; @@ -596,7 +596,7 @@ HgfsHandle2LocalId(HgfsHandle handle, // IN: Hgfs file handle found = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); return found; } @@ -632,7 +632,7 @@ HgfsHandle2ServerLock(HgfsHandle handle, // IN: Hgfs file handle ASSERT(lock); - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); fileNode = HgfsHandle2FileNode(handle, session); if (fileNode == NULL) { goto exit; @@ -642,7 +642,7 @@ HgfsHandle2ServerLock(HgfsHandle handle, // IN: Hgfs file handle found = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); return found; #else @@ -681,7 +681,8 @@ HgfsFileDesc2Handle(fileDesc fd, // IN: OS handle (file descriptor) 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) && @@ -692,7 +693,7 @@ HgfsFileDesc2Handle(fileDesc fd, // IN: OS handle (file descriptor) } } - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); return found; } @@ -728,7 +729,8 @@ HgfsHandle2ShareMode(HgfsHandle handle, // IN: Hgfs file handle return found; } - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + existingFileNode = HgfsHandle2FileNode(handle, session); if (existingFileNode == NULL) { goto exit_unlock; @@ -740,7 +742,8 @@ HgfsHandle2ShareMode(HgfsHandle handle, // IN: Hgfs file handle found = (nameStatus == HGFS_NAME_STATUS_COMPLETE); exit_unlock: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return found; } @@ -808,7 +811,8 @@ HgfsHandle2FileNameMode(HgfsHandle handle, // IN: Hgfs file handle return found; } - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + existingFileNode = HgfsHandle2FileNode(handle, session); if (existingFileNode == NULL) { goto exit_unlock; @@ -826,9 +830,11 @@ HgfsHandle2FileNameMode(HgfsHandle handle, // IN: Hgfs file handle found = TRUE; exit_unlock: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + *fileName = name; *fileNameSize = nameSize; + return found; } @@ -866,7 +872,8 @@ HgfsFileHasServerLock(const char *utf8Name, // IN: Name in UTF8 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) && @@ -880,7 +887,8 @@ HgfsFileHasServerLock(const char *utf8Name, // IN: Name in UTF8 } } - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return found; #else return FALSE; @@ -918,7 +926,8 @@ HgfsGetNodeCopy(HgfsHandle handle, // IN: Hgfs file handle ASSERT(copy); - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + original = HgfsHandle2FileNode(handle, session); if (original == NULL) { goto exit; @@ -948,7 +957,8 @@ HgfsGetNodeCopy(HgfsHandle handle, // IN: Hgfs file handle found = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return found; } @@ -980,7 +990,8 @@ HgfsHandleIsSequentialOpen(HgfsHandle handle, // IN: Hgfs file handle ASSERT(sequentialOpen); - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + node = HgfsHandle2FileNode(handle, session); if (node == NULL) { goto exit; @@ -990,7 +1001,8 @@ HgfsHandleIsSequentialOpen(HgfsHandle handle, // IN: Hgfs file handle success = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return success; } @@ -1022,7 +1034,8 @@ HgfsHandleIsSharedFolderOpen(HgfsHandle handle, // IN: Hgfs file handle ASSERT(sharedFolderOpen); - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + node = HgfsHandle2FileNode(handle, session); if (node == NULL) { goto exit; @@ -1032,7 +1045,8 @@ HgfsHandleIsSharedFolderOpen(HgfsHandle handle, // IN: Hgfs file handle success = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return success; } @@ -1064,7 +1078,8 @@ HgfsUpdateNodeFileDesc(HgfsHandle handle, // IN: Hgfs file handle HgfsFileNode *node; Bool updated = FALSE; - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + node = HgfsHandle2FileNode(handle, session); if (node == NULL) { goto exit; @@ -1075,7 +1090,8 @@ HgfsUpdateNodeFileDesc(HgfsHandle handle, // IN: Hgfs file handle updated = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return updated; } @@ -1110,7 +1126,8 @@ HgfsUpdateNodeServerLock(fileDesc fd, // IN: OS handle 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) { @@ -1122,7 +1139,8 @@ HgfsUpdateNodeServerLock(fileDesc fd, // IN: OS handle } } - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return updated; } @@ -1152,7 +1170,8 @@ HgfsUpdateNodeAppendFlag(HgfsHandle handle, // IN: Hgfs file handle HgfsFileNode *node; Bool updated = FALSE; - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + node = HgfsHandle2FileNode(handle, session); if (node == NULL) { goto exit; @@ -1164,7 +1183,8 @@ HgfsUpdateNodeAppendFlag(HgfsHandle handle, // IN: Hgfs file handle updated = TRUE; exit: - SyncMutex_Unlock(&session->nodeArrayLock); + MXUser_ReleaseExclLock(session->nodeArrayLock); + return updated; } @@ -1507,9 +1527,9 @@ static void 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); } @@ -1854,9 +1874,9 @@ HgfsIsServerLockAllowed(HgfsSessionInfo *session) // IN: session info { 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; } @@ -2053,7 +2073,7 @@ HgfsGetSearchCopy(HgfsHandle handle, // IN: Hgfs search handle ASSERT(copy); - SyncMutex_Lock(&session->searchArrayLock); + MXUser_AcquireExclLock(session->searchArrayLock); original = HgfsSearchHandle2Search(handle, session); if (original == NULL) { goto exit; @@ -2084,7 +2104,7 @@ HgfsGetSearchCopy(HgfsHandle handle, // IN: Hgfs search handle found = TRUE; exit: - SyncMutex_Unlock(&session->searchArrayLock); + MXUser_ReleaseExclLock(session->searchArrayLock); return found; } @@ -2236,13 +2256,15 @@ HgfsRemoveSearch(HgfsHandle handle, // IN: search 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; } @@ -2276,7 +2298,8 @@ HgfsGetSearchResult(HgfsHandle handle, // IN: Handle to search 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; @@ -2332,7 +2355,7 @@ HgfsGetSearchResult(HgfsHandle handle, // IN: Handle to search } out: - SyncMutex_Unlock(&session->searchArrayLock); + MXUser_ReleaseExclLock(session->searchArrayLock); return dent; } @@ -2416,7 +2439,8 @@ HgfsUpdateNodeNames(const char *oldLocalName, // IN: Name of file to look for newBufferLen = strlen(newLocalName); - SyncMutex_Lock(&session->nodeArrayLock); + MXUser_AcquireExclLock(session->nodeArrayLock); + for (i = 0; i < session->numNodes; i++) { fileNode = &session->nodeArray[i]; @@ -2440,7 +2464,8 @@ HgfsUpdateNodeNames(const char *oldLocalName, // IN: Name of file to look for fileNode->utf8NameLen = newBufferLen; } } - SyncMutex_Unlock(&session->nodeArrayLock); + + MXUser_ReleaseExclLock(session->nodeArrayLock); } @@ -2888,22 +2913,30 @@ HgfsServerSessionConnect(void *transportData, // IN: transport session co * 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__)); @@ -3030,7 +3063,6 @@ HgfsServerSessionClose(void *clientData) // IN: session context /* Remove, typically, the last reference, will teardown everything. */ HgfsServerSessionPut(session); - } @@ -3063,7 +3095,7 @@ HgfsServerExitSessionInternal(HgfsSessionInfo *session) // IN: session contex 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. */ @@ -3081,10 +3113,14 @@ HgfsServerExitSessionInternal(HgfsSessionInfo *session) // IN: session contex 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)) { @@ -3095,12 +3131,12 @@ HgfsServerExitSessionInternal(HgfsSessionInfo *session) // IN: session contex 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); } @@ -3365,7 +3401,7 @@ HgfsInvalidateSessionObjects(DblLnkLst_Links *shares, // IN: List of new shares 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, @@ -3407,9 +3443,9 @@ HgfsInvalidateSessionObjects(DblLnkLst_Links *shares, // IN: List of new shares } } - 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 @@ -3446,7 +3482,7 @@ HgfsInvalidateSessionObjects(DblLnkLst_Links *shares, // IN: List of new shares } } - SyncMutex_Unlock(&session->searchArrayLock); + MXUser_ReleaseExclLock(session->searchArrayLock); LOG(4, ("%s: Ending\n", __FUNCTION__)); } @@ -3904,7 +3940,8 @@ HgfsServerDumpDents(HgfsHandle searchHandle, // IN: Handle to dump dents from 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, @@ -3915,7 +3952,8 @@ HgfsServerDumpDents(HgfsHandle searchHandle, // IN: Handle to dump dents from Log("\"%s\"\n", search->dents[i]->d_name); } } - SyncMutex_Unlock(&session->searchArrayLock); + + MXUser_ReleaseExclLock(session->searchArrayLock); #endif } @@ -4125,7 +4163,8 @@ HgfsServerSearchRealDir(char const *baseDir, // IN: Directory to search ASSERT(handle); ASSERT(shareName); - SyncMutex_Lock(&session->searchArrayLock); + MXUser_AcquireExclLock(session->searchArrayLock); + search = HgfsAddNewSearch(baseDir, DIRECTORY_SEARCH_TYPE_DIR, shareName, rootDir, session); if (!search) { @@ -4159,7 +4198,7 @@ HgfsServerSearchRealDir(char const *baseDir, // IN: Directory to search *handle = HgfsSearch2SearchHandle(search); out: - SyncMutex_Unlock(&session->searchArrayLock); + MXUser_ReleaseExclLock(session->searchArrayLock); return status; } @@ -4202,7 +4241,8 @@ HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName, // IN: Name enumerator 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__)); @@ -4222,7 +4262,7 @@ HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName, // IN: Name enumerator *handle = HgfsSearch2SearchHandle(search); out: - SyncMutex_Unlock(&session->searchArrayLock); + MXUser_ReleaseExclLock(session->searchArrayLock); return status; } @@ -4253,9 +4293,9 @@ HgfsRemoveFromCache(HgfsHandle handle, // IN: Hgfs handle to the node { 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; } @@ -4284,9 +4324,9 @@ HgfsIsCached(HgfsHandle handle, // IN: Structure representing file node { 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; } @@ -4394,9 +4434,9 @@ HgfsAddToCache(HgfsHandle handle, // IN: HGFS file handle { 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; } @@ -4459,13 +4499,14 @@ HgfsCreateAndCacheFileNode(HgfsFileOpenInfo *openInfo, // IN: Open info struct 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; } @@ -4473,11 +4514,12 @@ HgfsCreateAndCacheFileNode(HgfsFileOpenInfo *openInfo, // IN: Open info struct 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; diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h index dc27d5d90..eb7ba5d3d 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h +++ b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h @@ -73,7 +73,7 @@ #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 @@ -285,7 +285,7 @@ typedef struct HgfsSessionInfo { HgfsSessionSendFunc *send; /* Lock to ensure some fileIO requests are atomic for a handle. */ - SyncMutex fileIOLock; + MXUserExclLock *fileIOLock; Atomic_uint32 refCount; /* Reference count for session. */ @@ -295,7 +295,7 @@ typedef struct HgfsSessionInfo { * 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; @@ -322,7 +322,7 @@ typedef struct HgfsSessionInfo { * 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; diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c b/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c index afe624ab5..468588ebf 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServerLinux.c @@ -57,7 +57,7 @@ #include "posix.h" #include "file.h" #include "util.h" -#include "syncMutex.h" +#include "userlock.h" #include "su.h" #include "codeset.h" #include "unicodeOperations.h" @@ -3675,7 +3675,9 @@ HgfsServerRead(char const *packetIn, // IN: incoming packet * 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 { @@ -3694,13 +3696,13 @@ HgfsServerRead(char const *packetIn, // IN: incoming packet 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; @@ -3853,7 +3855,8 @@ HgfsServerWrite(char const *packetIn, // IN: incoming packet * 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 { @@ -3872,13 +3875,13 @@ HgfsServerWrite(char const *packetIn, // IN: incoming packet 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; diff --git a/open-vm-tools/lib/include/foundryThreads.h b/open-vm-tools/lib/include/foundryThreads.h index 0263a4eba..9456e2e9f 100644 --- a/open-vm-tools/lib/include/foundryThreads.h +++ b/open-vm-tools/lib/include/foundryThreads.h @@ -35,6 +35,8 @@ extern "C"{ #include #endif +#include "util.h" + struct FoundryWorkerThread; typedef void (*FoundryThreadProc)(struct FoundryWorkerThread *threadState); diff --git a/open-vm-tools/lib/include/log.h b/open-vm-tools/lib/include/log.h index deaf999e9..3b1e38d9a 100644 --- a/open-vm-tools/lib/include/log.h +++ b/open-vm-tools/lib/include/log.h @@ -56,7 +56,6 @@ EXTERN Bool Log_InitForApp(const char *fileName, const char *config, 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); diff --git a/open-vm-tools/lib/include/mutex.h b/open-vm-tools/lib/include/mutex.h new file mode 100644 index 000000000..2d1b81c85 --- /dev/null +++ b/open-vm-tools/lib/include/mutex.h @@ -0,0 +1,547 @@ +/********************************************************* + * 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 // 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_ diff --git a/open-vm-tools/lib/include/syncMutex.h b/open-vm-tools/lib/include/syncMutex.h index d4e7f9a01..d53c7b582 100644 --- a/open-vm-tools/lib/include/syncMutex.h +++ b/open-vm-tools/lib/include/syncMutex.h @@ -71,6 +71,4 @@ Bool SyncMutex_Unlock(SyncMutex *that); Bool SyncMutex_Trylock(SyncMutex *that); #endif -SyncMutex *SyncMutex_CreateSingleton(Atomic_Ptr *lckStorage); - #endif // #ifndef _SYNC_MUTEX_H_ diff --git a/open-vm-tools/lib/include/userlock.h b/open-vm-tools/lib/include/userlock.h new file mode 100644 index 000000000..9071df816 --- /dev/null +++ b/open-vm-tools/lib/include/userlock.h @@ -0,0 +1,104 @@ +/********************************************************* + * 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_ diff --git a/open-vm-tools/lib/include/vcpuid.h b/open-vm-tools/lib/include/vcpuid.h new file mode 100644 index 000000000..a39addfa1 --- /dev/null +++ b/open-vm-tools/lib/include/vcpuid.h @@ -0,0 +1,53 @@ +/********************************************************* + * 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_ diff --git a/open-vm-tools/lib/include/vix.h b/open-vm-tools/lib/include/vix.h index 065f7c829..0398141c5 100644 --- a/open-vm-tools/lib/include/vix.h +++ b/open-vm-tools/lib/include/vix.h @@ -317,6 +317,7 @@ enum { 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, diff --git a/open-vm-tools/lib/include/vm_basic_defs.h b/open-vm-tools/lib/include/vm_basic_defs.h index ab3b52680..329f24975 100644 --- a/open-vm-tools/lib/include/vm_basic_defs.h +++ b/open-vm-tools/lib/include/vm_basic_defs.h @@ -657,4 +657,13 @@ typedef int pid_t; #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_ diff --git a/open-vm-tools/lib/include/vm_basic_types.h b/open-vm-tools/lib/include/vm_basic_types.h index 224655f4e..9959d9aed 100644 --- a/open-vm-tools/lib/include/vm_basic_types.h +++ b/open-vm-tools/lib/include/vm_basic_types.h @@ -950,6 +950,31 @@ typedef void * UserVA; # 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. */ @@ -1001,4 +1026,10 @@ typedef struct VMRect { } VMRect; #endif +/* + * ranked locks "everywhere" + */ + +typedef uint32 MX_Rank; + #endif /* _VM_BASIC_TYPES_H_ */ diff --git a/open-vm-tools/lib/include/vm_version.h b/open-vm-tools/lib/include/vm_version.h index 2d2f3bf2f..180c1bf7d 100644 --- a/open-vm-tools/lib/include/vm_version.h +++ b/open-vm-tools/lib/include/vm_version.h @@ -216,7 +216,7 @@ #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" diff --git a/open-vm-tools/lib/include/vmci_sockets.h b/open-vm-tools/lib/include/vmci_sockets.h index 6c11aed0a..7d00636b5 100644 --- a/open-vm-tools/lib/include/vmci_sockets.h +++ b/open-vm-tools/lib/include/vmci_sockets.h @@ -53,6 +53,7 @@ #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 diff --git a/open-vm-tools/lib/include/vthread.h b/open-vm-tools/lib/include/vthread.h new file mode 100644 index 000000000..930dba023 --- /dev/null +++ b/open-vm-tools/lib/include/vthread.h @@ -0,0 +1,323 @@ +/********************************************************* + * 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 +#include +#include +#endif +#ifdef _WIN32 +#include +#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_ diff --git a/open-vm-tools/lib/include/vthreadBase.h b/open-vm-tools/lib/include/vthreadBase.h new file mode 100644 index 000000000..0cb9c7d70 --- /dev/null +++ b/open-vm-tools/lib/include/vthreadBase.h @@ -0,0 +1,93 @@ +/********************************************************* + * 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 diff --git a/open-vm-tools/lib/lock/Makefile.am b/open-vm-tools/lib/lock/Makefile.am new file mode 100644 index 000000000..fd232dcde --- /dev/null +++ b/open-vm-tools/lib/lock/Makefile.am @@ -0,0 +1,32 @@ +################################################################################ +### 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@ + diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c new file mode 100644 index 000000000..22755c7eb --- /dev/null +++ b/open-vm-tools/lib/lock/ul.c @@ -0,0 +1,122 @@ +/********************************************************* + * 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; +} diff --git a/open-vm-tools/lib/lock/ulAcquire.c b/open-vm-tools/lib/lock/ulAcquire.c new file mode 100644 index 000000000..68fed439c --- /dev/null +++ b/open-vm-tools/lib/lock/ulAcquire.c @@ -0,0 +1,77 @@ +/********************************************************* + * 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()); +} diff --git a/open-vm-tools/lib/lock/ulCreate.c b/open-vm-tools/lib/lock/ulCreate.c new file mode 100644 index 000000000..820cb6cc3 --- /dev/null +++ b/open-vm-tools/lib/lock/ulCreate.c @@ -0,0 +1,112 @@ +/********************************************************* + * 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; +} diff --git a/open-vm-tools/lib/lock/ulDestroy.c b/open-vm-tools/lib/lock/ulDestroy.c new file mode 100644 index 000000000..73f52400d --- /dev/null +++ b/open-vm-tools/lib/lock/ulDestroy.c @@ -0,0 +1,84 @@ +/********************************************************* + * 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); + } +} diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h new file mode 100644 index 000000000..876d0ab58 --- /dev/null +++ b/open-vm-tools/lib/lock/ulInt.h @@ -0,0 +1,471 @@ +/********************************************************* + * 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 +#endif + +#include +#include + +#if defined(_WIN32) +typedef DWORD MXThreadID; +#else +#include +#include +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 diff --git a/open-vm-tools/lib/lock/ulIsLocked.c b/open-vm-tools/lib/lock/ulIsLocked.c new file mode 100644 index 000000000..8626199b0 --- /dev/null +++ b/open-vm-tools/lib/lock/ulIsLocked.c @@ -0,0 +1,70 @@ +/********************************************************* + * 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); +} + diff --git a/open-vm-tools/lib/lock/ulRWPosix.c b/open-vm-tools/lib/lock/ulRWPosix.c new file mode 100644 index 000000000..f22a1928b --- /dev/null +++ b/open-vm-tools/lib/lock/ulRWPosix.c @@ -0,0 +1,287 @@ +/********************************************************* + * 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 + +#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); + } +} diff --git a/open-vm-tools/lib/lock/ulRelease.c b/open-vm-tools/lib/lock/ulRelease.c new file mode 100644 index 000000000..dc2d724c9 --- /dev/null +++ b/open-vm-tools/lib/lock/ulRelease.c @@ -0,0 +1,101 @@ +/********************************************************* + * 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"); +} diff --git a/open-vm-tools/lib/lock/ulSingleton.c b/open-vm-tools/lib/lock/ulSingleton.c new file mode 100644 index 000000000..54c7f0eb6 --- /dev/null +++ b/open-vm-tools/lib/lock/ulSingleton.c @@ -0,0 +1,112 @@ +/********************************************************* + * 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; +} + diff --git a/open-vm-tools/lib/lock/ulTryAcquire.c b/open-vm-tools/lib/lock/ulTryAcquire.c new file mode 100644 index 000000000..e4dd8a2e9 --- /dev/null +++ b/open-vm-tools/lib/lock/ulTryAcquire.c @@ -0,0 +1,84 @@ +/********************************************************* + * 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()); +} diff --git a/open-vm-tools/lib/nothread/Makefile.am b/open-vm-tools/lib/nothread/Makefile.am new file mode 100644 index 000000000..bc630e32c --- /dev/null +++ b/open-vm-tools/lib/nothread/Makefile.am @@ -0,0 +1,24 @@ +################################################################################ +### 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@ + diff --git a/open-vm-tools/lib/nothread/vthreadUL.c b/open-vm-tools/lib/nothread/vthreadUL.c new file mode 100644 index 000000000..1d53cca4c --- /dev/null +++ b/open-vm-tools/lib/nothread/vthreadUL.c @@ -0,0 +1,365 @@ +/********************************************************* + * 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 +#include +#include +#if defined(_WIN32) +#include +#elif defined(__APPLE__) || defined(__GLIBC__) +#include +#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 diff --git a/open-vm-tools/lib/sync/syncMutexPthread.c b/open-vm-tools/lib/sync/syncMutexPthread.c index 25f31ddfc..d23776e78 100644 --- a/open-vm-tools/lib/sync/syncMutexPthread.c +++ b/open-vm-tools/lib/sync/syncMutexPthread.c @@ -138,56 +138,6 @@ SyncMutex_Unlock(SyncMutex *that) // IN } -/* - *----------------------------------------------------------------------------- - * - * 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; -} - - /* *----------------------------------------------------------------------------- * diff --git a/open-vm-tools/lib/unity/unity.c b/open-vm-tools/lib/unity/unity.c index 990f5e05b..9c8049b79 100644 --- a/open-vm-tools/lib/unity/unity.c +++ b/open-vm-tools/lib/unity/unity.c @@ -263,6 +263,13 @@ Unity_Init(GuestApp_Dict *conf, // IN 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"); /* @@ -312,6 +319,8 @@ Unity_Init(GuestApp_Dict *conf, // IN 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; } diff --git a/open-vm-tools/lib/unity/unityPlatform.h b/open-vm-tools/lib/unity/unityPlatform.h index a283a6179..ad1751dd0 100644 --- a/open-vm-tools/lib/unity/unityPlatform.h +++ b/open-vm-tools/lib/unity/unityPlatform.h @@ -131,6 +131,8 @@ void UnityPlatformSetActiveDnDDetWnd(UnityPlatform *up, UnityDnD *detWnd); 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); diff --git a/open-vm-tools/lib/unity/unityPlatformX11.c b/open-vm-tools/lib/unity/unityPlatformX11.c index 338f144e3..9c5cf012b 100644 --- a/open-vm-tools/lib/unity/unityPlatformX11.c +++ b/open-vm-tools/lib/unity/unityPlatformX11.c @@ -3010,6 +3010,29 @@ UnityPlatformUnstickWindow(UnityPlatform *up, // IN } +/* + *----------------------------------------------------------------------------- + * + * 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. diff --git a/open-vm-tools/lib/user/utilPosix.c b/open-vm-tools/lib/user/utilPosix.c index 657973d7b..85cdb3b40 100644 --- a/open-vm-tools/lib/user/utilPosix.c +++ b/open-vm-tools/lib/user/utilPosix.c @@ -53,7 +53,7 @@ #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" @@ -556,13 +556,16 @@ Util_GetSafeTmpDir(Bool useConf) // IN 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 @@ -636,7 +639,7 @@ Util_GetSafeTmpDir(Bool useConf) // IN } exit: - SyncMutex_Unlock(lck); + MXUser_ReleaseExclLock(lck); free(baseTmpDir); free(userName); diff --git a/open-vm-tools/libvmtools/Makefile.am b/open-vm-tools/libvmtools/Makefile.am index 9a4ea93f9..0a9fc7279 100644 --- a/open-vm-tools/libvmtools/Makefile.am +++ b/open-vm-tools/libvmtools/Makefile.am @@ -29,7 +29,6 @@ libvmtools_la_LIBADD += ../lib/guestInfo/libGuestInfo.la 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 @@ -46,6 +45,9 @@ libvmtools_la_LIBADD += ../lib/user/libUser.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@ @@ -74,6 +76,7 @@ libvmtools_la_CPPFLAGS += @GLIB2_CPPFLAGS@ 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 diff --git a/open-vm-tools/modules/linux/vmxnet/vmxnet.c b/open-vm-tools/modules/linux/vmxnet/vmxnet.c index 659f59a1d..22f5b6c53 100644 --- a/open-vm-tools/modules/linux/vmxnet/vmxnet.c +++ b/open-vm-tools/modules/linux/vmxnet/vmxnet.c @@ -2913,7 +2913,7 @@ vmxnet_load_multicast (struct net_device *dev) 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; diff --git a/open-vm-tools/modules/linux/vmxnet3/vmxnet3_drv.c b/open-vm-tools/modules/linux/vmxnet3/vmxnet3_drv.c index c51b07968..13f7b4ebc 100644 --- a/open-vm-tools/modules/linux/vmxnet3/vmxnet3_drv.c +++ b/open-vm-tools/modules/linux/vmxnet3/vmxnet3_drv.c @@ -2275,7 +2275,7 @@ vmxnet3_set_mac_addr(struct net_device *netdev, void *p) 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; } diff --git a/open-vm-tools/modules/shared/vmxnet/npa_defs.h b/open-vm-tools/modules/shared/vmxnet/npa_defs.h index a5830f1b8..2ce333aea 100644 --- a/open-vm-tools/modules/shared/vmxnet/npa_defs.h +++ b/open-vm-tools/modules/shared/vmxnet/npa_defs.h @@ -35,8 +35,10 @@ #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 */ @@ -65,7 +67,7 @@ struct NPA_PluginConf { 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; @@ -73,13 +75,14 @@ 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; diff --git a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h index 45e246df4..9e147a5d1 100644 --- a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h +++ b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h @@ -106,7 +106,9 @@ typedef enum { 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, diff --git a/open-vm-tools/toolbox/Makefile.am b/open-vm-tools/toolbox/Makefile.am index a223de54d..2540c994b 100644 --- a/open-vm-tools/toolbox/Makefile.am +++ b/open-vm-tools/toolbox/Makefile.am @@ -38,6 +38,8 @@ COMMON += ../lib/dict/libDict.la COMMON += ../lib/message/libMessage.la COMMON += ../lib/unicode/libUnicode.la COMMON += ../lib/sync/libSync.la +COMMON += ../lib/lock/libLock.la +COMMON += ../lib/nothread/libNothread.la COMMON += ../lib/misc/libMisc.la COMMON += ../lib/panicDefault/libPanicDefault.la COMMON += ../lib/panic/libPanic.la diff --git a/open-vm-tools/vmware-user/Makefile.am b/open-vm-tools/vmware-user/Makefile.am index c0781beec..11587dc8c 100644 --- a/open-vm-tools/vmware-user/Makefile.am +++ b/open-vm-tools/vmware-user/Makefile.am @@ -85,7 +85,6 @@ vmware_user_LDADD += ../lib/hgfs/libHgfs.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 @@ -96,12 +95,18 @@ if ENABLE_UNITY 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@