]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Internal branch sync. Included in this change:
authorVMware, Inc <>
Wed, 20 Jan 2010 21:22:41 +0000 (13:22 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Wed, 20 Jan 2010 21:22:41 +0000 (13:22 -0800)
. Fix an issue where only image data would be retrieved from the clipboard,
  instead of both image and text data.

. Changes in shared code that don't affect open-vm-tools functionality.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
15 files changed:
open-vm-tools/lib/dnd/dndClipboard.c
open-vm-tools/lib/include/dndClipboard.h
open-vm-tools/lib/include/guest_os.h
open-vm-tools/lib/include/hostinfo.h
open-vm-tools/lib/include/vix.h
open-vm-tools/lib/lock/mutexInt.h [new file with mode: 0644]
open-vm-tools/lib/lock/ul.c
open-vm-tools/lib/lock/ulAcquire.c
open-vm-tools/lib/lock/ulCreate.c
open-vm-tools/lib/lock/ulDestroy.c
open-vm-tools/lib/lock/ulInt.h
open-vm-tools/lib/lock/ulRWPosix.c
open-vm-tools/lib/lock/ulRelease.c
open-vm-tools/lib/lock/ulTryAcquire.c
open-vm-tools/lib/misc/hostinfo.c

index 7d3069e1ce7791fd03fe356f2f8f616643ac3a6d..0d36862d95b5e689c130da91725ecb4741aba2c6 100644 (file)
@@ -244,6 +244,13 @@ CPClipboard_SetItem(CPClipboard *clip,          // IN/OUT: the clipboard
 {
    CPClipItem *item;
    void *newBuf = NULL;
+   /*
+    * Image, rtf and text may be put into a clipboard at same time, and total
+    * size may be more than limit. Image data will be first dropped, then
+    * rtf data.
+    */
+   DND_CPFORMAT filterList[] = {CPFORMAT_IMG_PNG, CPFORMAT_RTF, CPFORMAT_TEXT};
+   int filterIndex = 0;
 
    ASSERT(clip);
 
@@ -259,31 +266,6 @@ CPClipboard_SetItem(CPClipboard *clip,          // IN/OUT: the clipboard
       return FALSE;
    }
 
-   if (CPFORMAT_RTF == fmt) {
-      size_t textSize = clip->items[CPFormatToIndex(CPFORMAT_TEXT)].size;
-      if ((textSize + size) >= CPCLIPITEM_MAX_SIZE_V3) {
-         /*
-          * If both CPFORMAT_TEXT and CPFORMAT_RTF are availabe but total
-          * size is over limit, only keep CPFORMAT_TEXT.
-          */
-         return TRUE;
-      }
-   }
-
-   if (CPFORMAT_TEXT == fmt) {
-      size_t rtfSize = clip->items[CPFormatToIndex(CPFORMAT_RTF)].size;
-      if ((rtfSize + size) >= CPCLIPITEM_MAX_SIZE_V3) {
-         /*
-          * If both CPFORMAT_TEXT and CPFORMAT_RTF are availabe but total
-          * size is over limit, remove data for CPFORMAT_RTF and add data
-          * for CPFORMAT_TEXT.
-          */
-         if (!CPClipboard_ClearItem(clip, CPFORMAT_RTF)) {
-            return FALSE;
-         }
-      }
-   }
-
    item = &clip->items[CPFormatToIndex(fmt)];
 
    if (clipitem) {
@@ -298,6 +280,15 @@ CPClipboard_SetItem(CPClipboard *clip,          // IN/OUT: the clipboard
    item->size = size;
    item->exists = TRUE;
 
+   /* Drop some data if total size is more than limit. */
+   while (CPClipboard_GetTotalSize(clip) >= CPCLIPITEM_MAX_SIZE_V3 &&
+          filterIndex < ARRAYSIZE(filterList)) {
+      if (!CPClipboard_ClearItem(clip, filterList[filterIndex])) {
+         return FALSE;
+      }
+      filterIndex++;
+   }
+
    return TRUE;
 }
 
@@ -448,6 +439,40 @@ CPClipboard_IsEmpty(const CPClipboard *clip)    // IN: the clipboard
 }
 
 
+/*
+ *----------------------------------------------------------------------------
+ *
+ * CPClipboard_GetTotalSize --
+ *
+ *      Get total buffer size of the clipboard.
+ *
+ * Results:
+ *      Total buffer size of the clipboard.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+size_t
+CPClipboard_GetTotalSize(const CPClipboard *clip) // IN: the clipboard
+{
+   unsigned int i = 0;
+   size_t totalSize = 0;
+
+   ASSERT(clip);
+
+   for (i = CPFORMAT_MIN; i < CPFORMAT_MAX; ++i) {
+      if (clip->items[CPFormatToIndex(i)].exists &&
+          clip->items[CPFormatToIndex(i)].size > 0) {
+         totalSize += clip->items[CPFormatToIndex(i)].size;
+      }
+   }
+   return totalSize;
+}
+
+
 /*
  *----------------------------------------------------------------------------
  *
index d7098bb42616e96d25a3fe457d96c6f130d1639f..9fa390cfd9f0b9e03090f4de7cb06725c331cb5d 100644 (file)
@@ -105,6 +105,7 @@ Bool CPClipboard_GetItem(const CPClipboard *clip, DND_CPFORMAT fmt,
                          void **buf, size_t *size);
 Bool CPClipboard_ItemExists(const CPClipboard *clip, DND_CPFORMAT fmt);
 Bool CPClipboard_IsEmpty(const CPClipboard *clip);
+size_t CPClipboard_GetTotalSize(const CPClipboard *clip);
 Bool CPClipboard_Copy(CPClipboard *dest, const CPClipboard *src);
 Bool CPClipboard_Serialize(const CPClipboard *clip, DynBuf *buf);
 Bool CPClipboard_Unserialize(CPClipboard *clip, void *buf, size_t len);
index 82613f382456012828f7fc6b65e735daaa6182c0..cd767f85f979796b89bdc353b79f4574f37a9f82 100644 (file)
@@ -86,6 +86,7 @@ typedef enum GuestOSType {
    GUEST_OS_WINSEVEN_64         = GUEST_OS_BASE + 48, // Windows 7
    GUEST_OS_WIN2008R2           = GUEST_OS_BASE + 49, // Server 2008 R2
    GUEST_OS_WIN2008R2_64        = GUEST_OS_BASE + 50, // Server 2008 R2
+   GUEST_OS_ECOMSTATION         = GUEST_OS_BASE + 51, // OS/2 variant
 } GuestOSType;
 
 
@@ -164,6 +165,8 @@ typedef enum GuestOSFamilyType {
                          BS(SOLARIS10_64) | BS(FREEBSD_64) | \
                          ALLDARWIN64 | BS(OTHER_64) | BS(VMKERNEL))
 
+#define ALLOS2          (BS(OS2) | BS(ECOMSTATION))
+
 
 /*
  * These constants are generated by GuestInfoGetOSName which is in
@@ -235,6 +238,7 @@ typedef enum GuestOSFamilyType {
 #define STR_OS_UNITEDLINUX        "UnitedLinux" 
 #define STR_OS_VALINUX            "VALinux" 
 #define STR_OS_YELLOW_DOG         "Yellow Dog"
+#define STR_OS_ECOMSTATION        "eComStation"
 
 /* Windows */
 #define STR_OS_WIN_31                   "win31"
index 024fced60d8803a1277144d57ad97eca981b82af..1586961bd97bc2f231edb752d39705c7bfc6c2b3 100644 (file)
@@ -20,7 +20,7 @@
  * hostinfo.h --
  *
  *      Interface to host-specific information functions
- *   
+ *
  */
 
 #if !defined(_HOSTINFO_H_)
@@ -130,6 +130,7 @@ typedef struct {
 
 
 extern uint32 Hostinfo_NumCPUs(void);
+extern char *Hostinfo_GetCpuidStr(void);
 extern Bool Hostinfo_GetCpuid(HostinfoCpuIdInfo *info);
 
 #if defined(VMX86_SERVER)
@@ -180,7 +181,7 @@ OS_TYPE Hostinfo_GetOSType(void);
 OS_DETAIL_TYPE Hostinfo_GetOSDetailType(void);
 
 Bool Hostinfo_GetPCFrequency(uint64 *pcHz);
-Bool Hostinfo_GetMhzOfProcessor(int32 processorNumber, 
+Bool Hostinfo_GetMhzOfProcessor(int32 processorNumber,
                                uint32 *currentMhz, uint32 *maxMhz);
 uint64 Hostinfo_SystemIdleTime(void);
 Bool Hostinfo_GetAllCpuid(CPUIDQuery *query);
index 0398141c5ebd9b14c90dd9a3ab9a3adf6d3c17aa..9b826ff9b2b4774dc19277827ce4392adb9096db 100644 (file)
@@ -318,6 +318,7 @@ enum {
    VIX_E_WRAPPER_SERVICEPROVIDER_NOT_FOUND      = 22003,
    VIX_E_WRAPPER_PLAYER_NOT_INSTALLED           = 22004,
    VIX_E_WRAPPER_RUNTIME_NOT_INSTALLED          = 22005,
+   VIX_E_WRAPPER_MULTIPLE_SERVICEPROVIDERS      = 22006,
 
    /* FuseMnt errors*/
    VIX_E_MNTAPI_MOUNTPT_NOT_FOUND               = 24000,
@@ -369,6 +370,20 @@ enum {
    VIX_E_MNTAPI_CREATE_PARTITIONTABLE_ERROR     = 24320,
    VIX_E_MNTAPI_OPEN_FAILURE                    = 24321,
    VIX_E_MNTAPI_VOLUME_NOT_WRITABLE             = 24322,
+
+   /* Network Errors */
+   VIX_E_NET_HTTP_UNSUPPORTED_PROTOCOL     = 30001,
+   VIX_E_NET_HTTP_URL_MALFORMAT            = 30003,
+   VIX_E_NET_HTTP_COULDNT_RESOLVE_PROXY    = 30005,
+   VIX_E_NET_HTTP_COULDNT_RESOLVE_HOST     = 30006,
+   VIX_E_NET_HTTP_COULDNT_CONNECT          = 30007,
+   VIX_E_NET_HTTP_HTTP_RETURNED_ERROR      = 30022,
+   VIX_E_NET_HTTP_OPERATION_TIMEDOUT       = 30028,
+   VIX_E_NET_HTTP_SSL_CONNECT_ERROR        = 30035,
+   VIX_E_NET_HTTP_TOO_MANY_REDIRECTS       = 30047,
+   VIX_E_NET_HTTP_TRANSFER                 = 30200,
+   VIX_E_NET_HTTP_SSL_SECURITY             = 30201,
+   VIX_E_NET_HTTP_GENERIC                  = 30202,
 };
 
 // {{ End VIX_ERROR }}
diff --git a/open-vm-tools/lib/lock/mutexInt.h b/open-vm-tools/lib/lock/mutexInt.h
new file mode 100644 (file)
index 0000000..d2eeca2
--- /dev/null
@@ -0,0 +1,254 @@
+/*********************************************************
+ * 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.
+ *
+ *********************************************************/
+
+/*
+ * mutexInt.h --
+ *
+ *     Internal interface for the Mutex module
+ */
+
+#ifndef _MUTEXINT_H_
+#define _MUTEXINT_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#include "mutex.h"
+#if defined VMX86_VMX || defined VMM || defined MONITOR_APP
+#include "usercall.h"
+#endif
+
+/*
+ * NOTE to Windows users on semaphores:
+ *
+ * The semaphores that are implemented here are for the implementation
+ * of the MX_* primitives.  They are used in a specialized way such that 
+ * they serve the purpose of the MX_* implementation. The Windows 
+ * implementation uses Windows Event objects and not Semaphore objects 
+ * for implementation reasons. 
+ * The Windows driver needs to access the Windows Event object during a 
+ * module call. The object lookup function in the driver can lookup up 
+ * Windows Event objects and not Windows Semaphore objects.  Since Windows
+ * Event objects have the proper semantics, they are used to implement
+ * our semaphores.
+ *
+ * Since the monitor is always compiled on Linux, SEMA_INVALID_HANDLE
+ * really has to be the same value on all hosts.  This nicely matches
+ * Windows' INVALID_HANDLE_VALUE, which is asserted in MXSemaphoreInit().
+ */ 
+
+#if defined VMX86_VMX || defined VMM || defined MONITOR_APP
+typedef struct MXSemaphoreRPC {
+   RPCBlock     rpc;
+   uint32       _pad0;
+   MXSemaphore  sema;
+} MXSemaphoreRPC;
+#endif
+
+void MXSemaphoreInit(MXSemaphore *sema);
+void MXSemaphoreInvalidate(MXSemaphore *sema);
+void MXSemaphoreDestroy(MXSemaphore *sema);
+void MXSemaphoreWait(MXSemaphore *sema, MX_Rank rank);
+Bool MXSemaphoreWaitTimeout(MXSemaphore *sema, MX_Rank rank, int maxWaitUS);
+Bool MXSemaphoreTryWait(MXSemaphore *sema);
+void MXSemaphoreSignal(MXSemaphore *sema);
+
+
+/*
+ * Locks
+ */
+
+#define MX_LOCK_ID_NULL  MX_MAX_LOCKS
+
+/*
+ * Each lock has an affiliate (per-lock) data structure. This data structure 
+ * is kept separately from the lock itself to make it visible across the 
+ * vmx/vmm divide, regardless of the visibility of the lock.
+ */
+
+typedef struct MXPerLock {
+   MXSemaphore   sema;                /* Semaphore for blocking.             */
+   Atomic_uint32 isActive;            /* Whether this "perLock" is active.   */
+#if MX_FAT_LOCKS != 0
+   uint32      pad;                   /* Pad for windows (align next field). */
+   uint64      lockCount;             /* #times this lock was acquired.      */
+   uint64      lockCountBlocking;     /* #times acquisition was blocking.    */
+   MX_Rank     rank;                  /* Rank of this lock; immutable.       */
+   MX_LockID   next;                  /* Next held lock on per-thread list.  */
+   char        name[MX_MAX_NAME_LEN]; /* Zero-terminated name for lock.      */
+#endif
+} MXPerLock;
+
+
+/*
+ * Condition variables. We use only CAS and the host binary semaphore
+ * primitive.
+ *
+ * We keep a list of waiters, who are awakened in FIFO order. Because it
+ * is impossible to append to the end of a singly-linked list using only
+ * CAS, we use an unusual representation of the queue waiters.
+ *
+ * The queue is represented as two lists, "head" and "tail." The first item in
+ * the queue appears in "head". Subsequent items in the queue may follow in
+ * "head". If "tail" is non-empty, it contains a list of queue items logically
+ * behind all those in "head", and _in reversed order_. I.e., if "tail" isn't
+ * empty, its _first_ item is the _last_ item in the queue.
+ *
+ * This way, entering an item into the queue always boils down to the simple,
+ * CAS-implementable operation of prepending an item to the head of a linked
+ * list: the "head" list if the queue is empty, and the "tail" list otherwise.
+ */
+
+#define MX_LIST_INVAL ((MXCVLink)-1U)
+
+/*
+ * Support for locks and condition variables
+ */
+
+typedef struct MXPerThread {
+#if MX_FAT_LOCKS != 0
+   uint64      lockCount;            /* #times this thread acquired a lock.  */
+   uint64      lockCountBlocking;    /* #times acquisition was blocking.     */
+   MX_LockID   first;                /* First lock held by this thread.      */
+   uint32      partiallyLocked;      /* Locks partially acquired by thread.  */
+#endif
+   MXSemaphore sema;                 /* sema for CV blocking                 */
+   MXCVLink    cvLink;               /* forward link for CV wait queue       */
+   Bool        initialized;
+   uint8       _pad[6];
+} MXPerThread;
+
+typedef struct MXState {
+#if defined(__i386__) || defined(__x86_64__)
+   uint64        startTSC;                  /* Init-time TSC.                */
+#endif
+   Atomic_uint32 numLocks;                  /* Number of active locks.       */
+   unsigned      spinLimit;                 /* Spin limit before blocking.   */
+   Bool          doneInit;                  /* To make init idempotent.      */
+   uint32        pad;                       /* Make windows and linux agree. */
+   MXPerLock     perLock[MX_MAX_LOCKS];     /* Indexed by lock id.           */
+   MXPerThread   perThread[VTHREAD_MAX_THREADS]; /* Indexed by thread id.    */
+} MXState;
+
+#ifdef VMM
+EXTERN SHARED_PER_VM MXState mxState;
+#else
+extern MXState *mxState;             /* Module state; in shared area. */
+#endif
+
+static INLINE MXState *
+GetMXState(void)
+{
+#ifdef VMM
+   return &mxState;
+#else
+   return mxState;
+#endif
+}
+
+/*
+ * Iterate "lid" over all locks held by "tid", which *must* be the 
+ * current thread to avoid races.
+ */
+
+#define FOR_ALL_LOCKS_HELD(tid, lid)     \
+   for (lid = GetPerThread(tid)->first;  \
+        lid != MX_LOCK_ID_NULL;          \
+        lid = GetPerLock(lid)->next)
+
+#define FOR_ALL_ACTIVE_LOCKS(lid)            \
+   for (lid = 0; lid < MX_MAX_LOCKS; lid++)  \
+      if (Atomic_Read(&GetPerLock(lid)->isActive))
+
+static INLINE MXPerLock *
+GetPerLock(MX_LockID lid)  // IN:
+{
+   ASSERT(lid < MX_MAX_LOCKS);
+
+   return GetMXState()->perLock + lid;
+}
+
+static INLINE MXPerThread *
+GetPerThread(VThreadID tid)  // IN:
+{
+   return GetMXState()->perThread + tid;
+}
+
+static INLINE MXPerThread *
+GetMyPerThread(void)
+{
+   return GetPerThread(VThread_CurID());
+}
+
+static INLINE MXSemaHandle
+MXSemaphoreGetSemaHandle(MXSemaphore *sema)  // IN:
+{
+#ifdef _WIN32
+   MXSemaHandle *ph = (MXSemaHandle *) &sema->waitHandle;
+
+   return *ph;
+#else
+   return sema->waitHandle;
+#endif
+}
+
+#ifdef _WIN32
+
+static INLINE void
+MXSemaphoreSetSemaHandle(MXSemaphore *sema,  // IN/OUT:
+                         MXSemaHandle h)     // IN:
+{
+   MXSemaHandle *ph = (MXSemaHandle *) &sema->waitHandle;
+   *ph = h;
+
+#ifndef _WIN64
+   /*
+    * This handle might be seen by a 64-bit vmmon, so make sure the
+    * upper 32-bits are set correctly.
+    */
+
+   if (h == (MXSemaHandle) VMW_INVALID_HANDLE) {
+      sema->signalHandle = (int) VMW_INVALID_HANDLE;
+   } else {
+      sema->signalHandle = 0;
+   }
+#endif // _WIN64
+}
+
+#endif // _WIN32
+
+#ifdef USERLEVEL
+void MXInvalidatePerThread(VThreadID tid);
+#endif
+
+
+/*
+ * Lock stats
+ */
+
+#if MX_STATS_LEVEL > 2
+void MXIncLockCount(void);
+#else
+#define MXIncLockCount()
+#endif
+
+#define MX_WAITTIMEOUT       1000   // milliseconds
+
+#endif // ifndef _MUTEXINT_H_
index 81b7ad876176048ea88f5f0e18b0ff40b334264a..75442cea1b8b714ee53f5f7e5e59e70f635bc89f 100644 (file)
  *
  *********************************************************/
 
-
 #include "vmware.h"
 #include "str.h"
 #include "util.h"
 #include "userlock.h"
 #include "ulInt.h"
+#include "mutexInt.h"
+
+#if defined(VMX86_DEBUG)
+#define MXUSER_MAX_LOCKS_PER_THREAD 24
+
+typedef struct {
+   uint32         lockNum;
+   MXUserHeader  *lockArray[MXUSER_MAX_LOCKS_PER_THREAD];
+} MXUserPerThread;
+
+static MXUserPerThread mxUserPerThread[VTHREAD_MAX_THREADS];
+#endif
 
 
 /*
@@ -50,6 +61,123 @@ MXUserIDHack(void)
 }
 
 
+#if defined(VMX86_DEBUG)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserAcquireRankCheck
+ *
+ *      Perform rank checking for lock acquisition.
+ *
+ * Results:
+ *      A panic on rank violation.
+ *
+ * Side effects:
+ *      Manifold.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUserAcquireRankCheck(MXUserHeader *header)  // IN:
+{
+   VThreadID tid = (*MXUserThreadCurID)();
+   MXUserPerThread *perThread = &mxUserPerThread[tid];
+
+   /* Hack until VThread_CurID is fixed */
+   if ((tid == VTHREAD_INVALID_ID) || (tid == VTHREAD_OTHER_ID)) {
+      return;
+   }
+
+   ASSERT_NOT_IMPLEMENTED(perThread->lockNum < MXUSER_MAX_LOCKS_PER_THREAD);
+
+   perThread->lockArray[perThread->lockNum++] = header;
+
+   if (header->lockRank != RANK_UNRANKED) {
+      uint32 i;
+      MX_Rank maxRank;
+
+      /* Check MX locks when they are present */
+      maxRank = (mxState) ? MX_CurrentRank() : RANK_UNRANKED;
+
+      for (i = 0; i < perThread->lockNum; i++) {
+         maxRank = MAX(perThread->lockArray[i]->lockRank, maxRank);
+      }
+
+      if (header->lockRank <= maxRank) {
+         Warning("%s: lock rank violation by thread %s\n", __FUNCTION__,
+                 VThread_CurName());
+         Warning("%s: locks held:\n", __FUNCTION__);
+
+         for (i = 0; i < perThread->lockNum; i++) {
+            MXUserHeader *hdr = perThread->lockArray[i];
+
+            Warning("\tMXUser lock %s (@%p) rank %d\n", hdr->lockName, hdr,
+                    hdr->lockRank);
+         }
+
+         if (mxState) {
+            MX_LockID lid;
+
+            FOR_ALL_LOCKS_HELD(tid, lid) {
+               MXPerLock *perLock = GetPerLock(lid);
+
+               Warning("\tMX lock %s (@%u) rank %d\n", perLock->name,
+                       lid, perLock->rank);
+            }
+         }
+
+         MXUserDumpAndPanic(header, "%s: rank violation\n", __FUNCTION__);
+      }
+   }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserReleaseRankCheck
+ *
+ *      Perform rank checking for lock release.
+ *
+ * Results:
+ *      A panic.
+ *
+ * Side effects:
+ *      Manifold.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+MXUserReleaseRankCheck(MXUserHeader *header)  // IN:
+{
+   uint32 i;
+   VThreadID tid = (*MXUserThreadCurID)();
+   MXUserPerThread *perThread = &mxUserPerThread[tid];
+
+   /* Hack until VThread_CurID is fixed */
+   if ((tid == VTHREAD_INVALID_ID) || (tid == VTHREAD_OTHER_ID)) {
+      return;
+   }
+
+   for (i = 0; i < perThread->lockNum; i++) {
+      if (perThread->lockArray[i] == header) {
+         break;
+      }
+   }
+
+   ASSERT_NOT_IMPLEMENTED(i < perThread->lockNum);  // better find it
+
+   if (i < perThread->lockNum - 1) {
+      perThread->lockArray[i] = perThread->lockArray[perThread->lockNum - 1];
+   }
+
+   perThread->lockNum--;
+}
+#endif
+
+
 /*
  *-----------------------------------------------------------------------------
  *
index 02450d9701f59d1adfe4105744bda9a190da65f0..e95edea4962fe3ac5d1eeb17c426d5a418792818 100644 (file)
@@ -16,7 +16,6 @@
  *
  *********************************************************/
 
-
 #include "vmware.h"
 #include "userlock.h"
 #include "ulInt.h"
@@ -43,11 +42,13 @@ MXUser_AcquireExclLock(MXUserExclLock *lock) // IN/OUT:
 {
    ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
 
+   MXUserAcquireRankCheck(&lock->lockHeader);
+
    MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress());
 
    if (MXRecLockCount(&lock->lockRecursive) > 1) {
       MXUserDumpAndPanic(&lock->lockHeader,
-                         "%s: Acquire on an acquired exclusive lock",
+                         "%s: Acquire on an acquired exclusive lock\n",
                          __FUNCTION__);
    }
 }
@@ -76,5 +77,7 @@ MXUser_AcquireRecLock(MXUserRecLock *lock)  // IN/OUT:
 {
    ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
 
+   MXUserAcquireRankCheck(&lock->lockHeader);
+
    MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress());
 }
index 6f95acca22129783afc8e106d061e8b1ddd2a171..27b03cdb3aceadd4fd3c8de3019c067589ca9df3 100644 (file)
@@ -16,7 +16,6 @@
  *
  *********************************************************/
 
-
 #include "vmware.h"
 #include "str.h"
 #include "util.h"
@@ -134,14 +133,16 @@ MXUserDumpRecLock(MXUserHeader *header)  // IN:
    Warning("\tname %s\n", lock->lockHeader.lockName);
    Warning("\trank %d\n", lock->lockHeader.lockRank);
 
-   Warning("\tcount %u\n", lock->lockRecursive.lockCount);
+   if (lock->lockVmm == NULL) {
+      Warning("\tcount %u\n", lock->lockRecursive.lockCount);
 
 #if defined(VMX86_DEBUG)
-   Warning("\tcaller %p\n", lock->lockRecursive.lockCaller);
-   Warning("\tVThreadID %d\n", (int) lock->lockRecursive.lockVThreadID);
+      Warning("\tcaller %p\n", lock->lockRecursive.lockCaller);
+      Warning("\tVThreadID %d\n", (int) lock->lockRecursive.lockVThreadID);
 #endif
-
-   Warning("\tlockVmm %p\n", lock->lockVmm);
+   } else {
+      Warning("\tlockVmm %p\n", lock->lockVmm);
+   }
 }
 
 
index c2b57799cc5eadf68fd9449ce9ee82d5c3a4e929..af2d23ca94a22509d168125cb2d26cf2048e4caf 100644 (file)
@@ -44,7 +44,7 @@ MXUser_DestroyExclLock(MXUserExclLock *lock)  // IN:
 
       if (MXRecLockCount(&lock->lockRecursive) > 0) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: Destroy of an acquired exclusive lock",
+                            "%s: Destroy of an acquired exclusive lock\n",
                             __FUNCTION__);
       }
 
@@ -79,7 +79,7 @@ MXUser_DestroyRecLock(MXUserRecLock *lock)  // IN:
 
       if (MXRecLockCount(&lock->lockRecursive) > 0) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: Destroy of an acquired recursive lock",
+                            "%s: Destroy of an acquired recursive lock\n",
                             __FUNCTION__);
       }
 
index 15fdd61f7cab10a627c9c6a6a43bda3a4d120114..fb8326710c63f229a1154bb2cd2cd1f55b02a64f 100644 (file)
@@ -422,4 +422,21 @@ Bool MXUserIsAllUnlocked(const MXUserRWLock *lock);
 void MXUserDumpAndPanic(MXUserHeader *header,
                         const char *fmt,
                         ...);
+
+#if defined(VMX86_DEBUG)
+void MXUserAcquireRankCheck(MXUserHeader *header);
+void MXUserReleaseRankCheck(MXUserHeader *header);
+#else
+static INLINE void
+MXUserAcquireRankCheck(MXUserHeader *header)
+{
+   return;
+}
+
+static INLINE void
+MXUserReleaseRankCheck(MXUserHeader *header)
+{
+   return;
+}
+#endif
 #endif
index ee316e85b561adee682269a8a1f3eb1b6064f448..10cfbc9e65d257bda1cd41a3dd8fdfc459d5eda3 100644 (file)
@@ -95,8 +95,6 @@ MXUser_CreateRWLock(const char *userName,  // IN:
    char *properName;
    MXUserRWLock *lock;
 
-   ASSERT(rank == RANK_UNRANKED);  // NOT FOR LONG
-
    lock = Util_SafeCalloc(1, sizeof(*lock));
 
    if (userName == NULL) {
@@ -162,19 +160,21 @@ MXUser_AcquireForRead(MXUserRWLock *lock)  // IN/OUT:
 
    ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
 
+   MXUserAcquireRankCheck(&lock->lockHeader);
+
 #if defined(PTHREAD_RWLOCK_INITIALIZER)
    err = pthread_rwlock_rdlock(&lock->lockReadWrite);
 
    if (err == 0) {
       if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: AcquireForRead after AcquireForRead",
+                            "%s: AcquireForRead after AcquireForRead\n",
                             __FUNCTION__);
       }
    } else {
-      MXUserDumpAndPanic(&lock->lockHeader, "%s: %s",
-                         (err == EDEADLK) ? "Deadlock detected (%d)" :
-                                            "Internal error (%d)",
+      MXUserDumpAndPanic(&lock->lockHeader,
+                         (err == EDEADLK) ? "%s: Deadlock detected (%d)\n" :
+                                            "%s: Internal error (%d)\n",
                          __FUNCTION__, err);
    }
 #else
@@ -183,12 +183,12 @@ MXUser_AcquireForRead(MXUserRWLock *lock)  // IN/OUT:
    if (lock->lockTaken[self] != RW_UNLOCKED) {
       if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: AcquireForRead after AcquireForRead"
-                            __FUNCTION__, self);
+                            "%s: AcquireForRead after AcquireForRead\n"
+                            __FUNCTION__);
       } else {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: AcquireForRead after AcquireForWrite"
-                            __FUNCTION__, self);
+                            "%s: AcquireForRead after AcquireForWrite\n"
+                            __FUNCTION__);
       }
    }
 
@@ -226,13 +226,15 @@ MXUser_AcquireForWrite(MXUserRWLock *lock)  // IN/OUT:
 
    ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
 
+   MXUserAcquireRankCheck(&lock->lockHeader);
+
 #if defined(PTHREAD_RWLOCK_INITIALIZER)
    err = pthread_rwlock_wrlock(&lock->lockReadWrite);
 
    if (err != 0) {
-      MXUserDumpAndPanic(&lock->lockHeader, "%s: %s",
-                         (err == EDEADLK) ? "Deadlock detected (%d)" :
-                                            "Internal error (%d)",
+      MXUserDumpAndPanic(&lock->lockHeader,
+                         (err == EDEADLK) ? "%s: Deadlock detected (%d)\n" :
+                                            "%s: Internal error (%d)\n",
                          __FUNCTION__, err);
    }
 #else
@@ -241,11 +243,11 @@ MXUser_AcquireForWrite(MXUserRWLock *lock)  // IN/OUT:
    if (lock->lockTaken[self] != RW_UNLOCKED) {
       if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: AcquireForRead after AcquireForWrite"
+                            "%s: AcquireForRead after AcquireForWrite\n"
                             __FUNCTION__);
       } else {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: AcquireForWrite after AcquireForWrite"
+                            "%s: AcquireForWrite after AcquireForWrite\n"
                             __FUNCTION__);
       }
    }
@@ -283,10 +285,12 @@ MXUser_ReleaseRWLock(MXUserRWLock *lock)  // IN/OUT:
 
    if (myState == RW_UNLOCKED) {
       MXUserDumpAndPanic(&lock->lockHeader,
-                         "%s: Release of read-lock not by owner (%d)",
+                         "%s: Release of read-lock not by owner (%d)\n",
                          __FUNCTION__, self);
    }
 
+   MXUserReleaseRankCheck(&lock->lockHeader);
+
    lock->lockTaken[self] = RW_UNLOCKED;
 
 #if defined(PTHREAD_RWLOCK_INITIALIZER)
@@ -326,7 +330,7 @@ MXUser_DestroyRWLock(MXUserRWLock *lock)  // IN:
 
       if (!MXUserIsAllUnlocked(lock)) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: Destroy on read-lock while still acquired",
+                            "%s: Destroy on read-lock while still acquired\n",
                             __FUNCTION__);
       }
 
index ae9fa95a752bc9c9c95f322538efe1e931a6371e..a4be89378b95294b3575da577439a84a140754a0 100644 (file)
@@ -45,15 +45,17 @@ MXUser_ReleaseExclLock(MXUserExclLock *lock)  // IN/OUT:
    if (!MXRecLockIsOwner(&lock->lockRecursive)) {
       if (MXRecLockCount(&lock->lockRecursive) == 0) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: Release of an unacquired exclusive lock",
+                            "%s: Release of an unacquired exclusive lock\n",
                             __FUNCTION__);
       } else {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: Release of owned exclusive lock",
+                            "%s: Release of owned exclusive lock\n",
                             __FUNCTION__);
       }
    }
 
+   MXUserReleaseRankCheck(&lock->lockHeader);
+
    MXRecLockRelease(&lock->lockRecursive);
 }
 
@@ -82,14 +84,16 @@ MXUser_ReleaseRecLock(MXUserRecLock *lock)  // IN/OUT:
    if (!MXRecLockIsOwner(&lock->lockRecursive)) {
       if (MXRecLockCount(&lock->lockRecursive) == 0) {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: Release of an unacquired recursive lock",
+                            "%s: Release of an unacquired recursive lock\n",
                             __FUNCTION__);
       } else {
          MXUserDumpAndPanic(&lock->lockHeader,
-                            "%s: Release of owned recursive lock",
+                            "%s: Release of owned recursive lock\n",
                             __FUNCTION__);
       }
    }
 
+   MXUserReleaseRankCheck(&lock->lockHeader);
+
    MXRecLockRelease(&lock->lockRecursive);
 }
index 8379d69cb3b85c7f1851e2368d0862172a72f908..cadfd502245e8fc9d8e8e325200ced0999e10f9d 100644 (file)
@@ -16,7 +16,6 @@
  *
  *********************************************************/
 
-
 #include "vmware.h"
 #include "userlock.h"
 #include "ulInt.h"
@@ -48,10 +47,14 @@ MXUser_TryAcquireExclLock(MXUserExclLock *lock)  // IN/OUT:
 
    success = MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress());
 
-   if (success && (MXRecLockCount(&lock->lockRecursive) > 1)) {
-      MXUserDumpAndPanic(&lock->lockHeader,
-                         "%s: Acquire on an acquired exclusive lock",
-                         __FUNCTION__);
+   if (success) {
+      if (MXRecLockCount(&lock->lockRecursive) > 1) {
+         MXUserDumpAndPanic(&lock->lockHeader,
+                            "%s: Acquire on an acquired exclusive lock\n",
+                            __FUNCTION__);
+      }
+
+      MXUserAcquireRankCheck(&lock->lockHeader);
    }
 
    return success;
@@ -80,7 +83,15 @@ MXUser_TryAcquireExclLock(MXUserExclLock *lock)  // IN/OUT:
 Bool
 MXUser_TryAcquireRecLock(MXUserRecLock *lock)  // IN/OUT:
 {
+   Bool success;
+
    ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE);
 
-   return MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress());
+   success = MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress());
+
+   if (success) {
+      MXUserAcquireRankCheck(&lock->lockHeader);
+   }
+
+   return success;
 }
index 39e2c82f4a8db1ee01ec46fb5b0600adcc1e7612..c175dad5d2b4ecc450aa77970f26f9442f75517e 100644 (file)
@@ -31,6 +31,8 @@
 #endif
 #include "hostinfo.h"
 #include "util.h"
+#include "str.h"
+#include "dynbuf.h"
 
 #define LOGLEVEL_MODULE hostinfo
 #include "loglevel_user.h"
@@ -102,6 +104,111 @@ HostInfoGetAMDCPUCount(CPUIDSummary *cpuid,       // IN
 #endif // defined(__i386__) || defined(__x86_64__)
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HostInfoGetCpuidStrSection --
+ *
+ *       Append a section (either low or high) of CPUID as a string in DynBuf.
+ *       E.g.
+ *          00000000:00000005756E65476C65746E49656E69-
+ *          00000001:00000F4A000208000000649DBFEBFBFF-
+ *       or
+ *          80000000:80000008000000000000000000000000-
+ *          80000001:00000000000000000000000120100000-
+ *          80000008:00003024000000000000000000000000-
+ *
+ *       The returned eax of args[0] is used to determine the upper bound for
+ *       the following input arguments. And the input args should be in ascending
+ *       order.
+ *
+ * Results:
+ *       None. The string will be appended in buf.
+ *
+ * Side effect:
+ *       None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HostInfoGetCpuidStrSection(const uint32 args[],    // IN: input eax arguments
+                           const size_t args_size, // IN: size of the argument array
+                           DynBuf *buf)            // IN/OUT: result string in DynBuf
+{
+   static const char format[] = "%08X:%08X%08X%08X%08X-";
+   CPUIDRegs reg;
+   uint32 max_arg;
+   char temp[64];
+   int i;
+
+   __GET_CPUID(args[0], &reg);
+   max_arg = reg.eax;
+   if (max_arg < args[0]) {
+      Warning(LGPFX" No CPUID information available. Based = %08X.\n", args[0]);
+      return;
+   }
+   DynBuf_Append(buf, temp,
+      Str_Sprintf(temp, sizeof temp, format, args[0], reg.eax, reg.ebx, reg.ecx, reg.edx));
+
+   for (i = 1; i < args_size && args[i] <= max_arg; i++) {
+      ASSERT(args[i] > args[i - 1]); // Ascending order.
+      __GET_CPUID(args[i], &reg);
+
+      DynBuf_Append(buf, temp,
+         Str_Sprintf(temp, sizeof temp, format, args[i], reg.eax, reg.ebx, reg.ecx, reg.edx));
+   }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Hostinfo_GetCpuidStr --
+ *
+ *       Get the basic and extended CPUID as a string. E.g.
+ *          00000000:00000005756E65476C65746E49656E69-
+ *          00000001:00000F4A000208000000649DBFEBFBFF-
+ *          80000000:80000008000000000000000000000000-
+ *          80000001:00000000000000000000000120100000-
+ *          80000008:00003024000000000000000000000000
+ *
+ *       If the extended CPUID is not available, only returns the basic CPUID.
+ *
+ * Results:
+ *       The CPUID string if the processor supports the CPUID instruction and this
+ *       is a processor we recognize. It should never fail, since it would at least
+ *       return leaf 0. Caller needs to free the returned string.
+ *
+ * Side effect:
+ *       None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char *
+Hostinfo_GetCpuidStr(void)
+{
+   static const uint32 basic_args[] = {0x0, 0x1, 0xa};
+   static const uint32 extended_args[] = {0x80000000, 0x80000001, 0x80000008};
+   DynBuf buf;
+   char *result;
+
+   DynBuf_Init(&buf);
+
+   HostInfoGetCpuidStrSection(basic_args, ARRAYSIZE(basic_args), &buf);
+   HostInfoGetCpuidStrSection(extended_args, ARRAYSIZE(extended_args), &buf);
+
+   // Trim buffer and set NULL character to replace last '-'.
+   DynBuf_Trim(&buf);
+   result = (char*)DynBuf_Get(&buf);
+   ASSERT(result && result[0]); // We should at least get result from eax = 0x0.
+   result[DynBuf_GetSize(&buf) - 1] = '\0';
+
+   return DynBuf_Detach(&buf);
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -217,7 +324,7 @@ Hostinfo_GetCpuid(HostinfoCpuIdInfo *info) // OUT
       Log(LGPFX" hyperthreading disabled, setting number of threads per core "
                "to 1.\n");
       numThreadsPerCore = 1;
-   } 
+   }
 #endif
 
    info->numPhysCPUs = info->numLogCPUs / (numCoresPerPCPU *
@@ -349,7 +456,7 @@ Hostinfo_TouchXen(void)
    CPUIDRegs regs;
    uint32 name[4];
 
-   /* 
+   /*
     * PV mode: ud2a "xen" cpuid (faults on native hardware).
     * (Only Linux can run PV, so skip others here).
     * Since PV cannot trap CPUID, this is a Xen hook.
@@ -376,7 +483,7 @@ Hostinfo_TouchXen(void)
    /* Passed checks.  But native and anything non-Xen would #UD before here. */
    NOT_TESTED();
    Log("Xen detected but hypervisor unrecognized (Xen variant?)\n");
-   Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n", 
+   Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n",
        regs.eax, regs.ebx, regs.ecx, regs.edx);
 #endif