]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
MXUser Semaphores - nanosecond resolution wait times
authorJohn Wolfe <jwolfe@vmware.com>
Tue, 22 Dec 2020 20:22:03 +0000 (12:22 -0800)
committerJohn Wolfe <jwolfe@vmware.com>
Tue, 22 Dec 2020 20:22:03 +0000 (12:22 -0800)
The graphics team requested the ability to have semaphore wait times
less than a millisecond.  This would greatly improve some graphics
operations.  Since POSIX platforms (i.e. ESXi, MacOS, Linux) support
nanosecond resolution for semaphore wait times, a new timed semaphore
wait routine with nanosecond resolution is introduced.

open-vm-tools/lib/include/userlock.h
open-vm-tools/lib/lock/ulSema.c

index 7a6ca5df60856aa145821007d57513bddc03d005..b58b6630555d31378ca65359a424ae6fd3e317e2 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2020 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
@@ -88,7 +88,7 @@ void MXUser_WaitCondVarExclLock(MXUserExclLock *lock,
 
 void MXUser_TimedWaitCondVarExclLock(MXUserExclLock *lock,
                                      MXUserCondVar *condVar,
-                                     uint32 waitTimeMsec);
+                                     uint32 waitTimeMS);
 
 Bool MXUser_EnableStatsExclLock(MXUserExclLock *lock,
                                 Bool trackAcquisitionTime,
@@ -151,7 +151,7 @@ void MXUser_WaitCondVarRecLock(MXUserRecLock *lock,
 
 void MXUser_TimedWaitCondVarRecLock(MXUserRecLock *lock,
                                     MXUserCondVar *condVar,
-                                    uint32 waitTimeMsec);
+                                    uint32 waitTimeMS);
 
 void MXUser_IncRefRecLock(MXUserRecLock *lock);
 
@@ -262,7 +262,9 @@ void MXUser_DownSemaphore(MXUserSemaphore *sema);
 Bool MXUser_TryDownSemaphore(MXUserSemaphore *sema);
 
 Bool MXUser_TimedDownSemaphore(MXUserSemaphore *sema,
-                               uint32 waitTimeMsec);
+                               uint32 waitTimeMS);
+Bool MXUser_TimedDownSemaphoreNS(MXUserSemaphore *sema,
+                                 uint64 waitTimeNS);
 
 MXUserSemaphore *MXUser_CreateSingletonSemaphore(Atomic_Ptr *semaStorage,
                                                  const char *name,
index 904e05b4508dd92da829d2e45746494dbf6d6e77..aabb087ccd292f1ee45d166b14b31366fab2716f 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2010-2019 VMware, Inc. All rights reserved.
+ * Copyright (C) 2010-2020 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
@@ -41,7 +41,8 @@
 #include "windowsu.h"
 #endif
 
-#define MXUSER_A_BILLION (1000 * 1000 * 1000)
+#define MXUSER_A_MILLION (1000 * 1000)
+#define MXUSER_A_BILLION (1000 * MXUSER_A_MILLION)
 
 #if defined(_WIN32)
 typedef HANDLE NativeSemaphore;
@@ -114,13 +115,19 @@ MXUserDestroy(NativeSemaphore *sema)  // IN:
 
 static int
 MXUserTimedDown(NativeSemaphore *sema,  // IN:
-                uint32 waitTimeMsec,    // IN:
+                uint64 waitTimeNS,      // IN:
                 Bool *downOccurred)     // OUT:
 {
     int err;
     DWORD status;
+    const uint64 maxWaitTimeMS = (uint64) 0x7FFFFFFF;
+    uint64 waitTimeMS = CEILING(waitTimeNS, (uint64) MXUSER_A_MILLION);
 
-    status = WaitForSingleObject(*sema, waitTimeMsec);
+    if (waitTimeMS > maxWaitTimeMS) {
+       waitTimeMS = maxWaitTimeMS;
+    }
+
+    status = WaitForSingleObject(*sema, (int) waitTimeMS);
 
     switch (status) {
        case WAIT_OBJECT_0:  // The down (decrement) occurred
@@ -198,12 +205,12 @@ MXUserDestroy(NativeSemaphore *sema)  // IN:
 
 static int
 MXUserTimedDown(NativeSemaphore *sema,  // IN:
-                uint32 waitTimeMsec,    // IN:
+                uint64 waitTimeNS,      // IN:
                 Bool *downOccurred)     // OUT:
 {
-   int64 nsecWait = 1000000LL * (int64)waitTimeMsec;
-   dispatch_time_t deadline = dispatch_time(DISPATCH_TIME_NOW, nsecWait);
+   dispatch_time_t deadline = dispatch_time(DISPATCH_TIME_NOW, waitTimeNS);
    *downOccurred = dispatch_semaphore_wait(*sema, deadline) == 0;
+
    return 0;
 }
 
@@ -260,7 +267,7 @@ MXUserDown(NativeSemaphore *sema)  // IN:
 
 static int
 MXUserTimedDown(NativeSemaphore *sema,  // IN:
-                uint32 waitTimeMsec,    // IN:
+                uint64 waitTimeNS,      // IN:
                 Bool *downOccurred)     // OUT:
 {
    int err;
@@ -277,7 +284,7 @@ MXUserTimedDown(NativeSemaphore *sema,  // IN:
    gettimeofday(&curTime, NULL);
    endNS = ((uint64) curTime.tv_sec * MXUSER_A_BILLION) +
            ((uint64) curTime.tv_usec * 1000) +
-           ((uint64) waitTimeMsec * (1000 * 1000));
+           waitTimeNS;
 
    endTime.tv_sec = (time_t) (endNS / MXUSER_A_BILLION);
    endTime.tv_nsec = (long int) (endNS % MXUSER_A_BILLION);
@@ -579,6 +586,7 @@ MXUser_DownSemaphore(MXUserSemaphore *sema)  // IN/OUT:
    int err;
 
    ASSERT(sema != NULL);
+
    MXUserValidateHeader(&sema->header, MXUSER_TYPE_SEMA);
 
    Atomic_Inc(&sema->activeUserCount);
@@ -635,12 +643,18 @@ MXUser_DownSemaphore(MXUserSemaphore *sema)  // IN/OUT:
 /*
  *-----------------------------------------------------------------------------
  *
- * MXUser_TimedDownSemaphore --
+ * MXUser_TimedDownSemaphoreNS --
  *
  *      Perform a down (P; probeer te verlagen; "try to reduce") operation
  *      on a semaphore with a timeout. The wait time will always have elapsed
  *      before the routine returns.
  *
+ *      NOT ALL SUPPORTED PLATFORMS CAN NATIVELY HANDLE WAIT TIMES OF LESS
+ *      THAN A MILLISECOND. WAIT TIMES WILL BE ROUNDED UP WHEN NECESSARY.
+ *
+ *      WAIT TIMES LONGER THAN A SUPPORTED PLATFORM CAN SUPPORT WILL BE
+ *      SET TO THE MAXIMUM POSSIBLE.
+ *
  * Results:
  *      TRUE   Down operation occurred (count has been decremented)
  *      FALSE  Down operation did not occur (time out occurred)
@@ -652,13 +666,14 @@ MXUser_DownSemaphore(MXUserSemaphore *sema)  // IN/OUT:
  */
 
 Bool
-MXUser_TimedDownSemaphore(MXUserSemaphore *sema,  // IN/OUT:
-                          uint32 waitTimeMsec)    // IN:
+MXUser_TimedDownSemaphoreNS(MXUserSemaphore *sema,  // IN/OUT:
+                            uint64 waitTimeNS)      // IN:
 {
    int err;
    Bool downOccurred = FALSE;
 
    ASSERT(sema != NULL);
+
    MXUserValidateHeader(&sema->header, MXUSER_TYPE_SEMA);
 
    Atomic_Inc(&sema->activeUserCount);
@@ -682,7 +697,7 @@ MXUser_TimedDownSemaphore(MXUserSemaphore *sema,  // IN/OUT:
          if (tryDownSuccess) {
             downOccurred = TRUE;
          } else {
-            err = MXUserTimedDown(&sema->nativeSemaphore, waitTimeMsec,
+            err = MXUserTimedDown(&sema->nativeSemaphore, waitTimeNS,
                                   &downOccurred);
          }
       }
@@ -702,7 +717,7 @@ MXUser_TimedDownSemaphore(MXUserSemaphore *sema,  // IN/OUT:
          }
       }
    } else {
-      err = MXUserTimedDown(&sema->nativeSemaphore, waitTimeMsec,
+      err = MXUserTimedDown(&sema->nativeSemaphore, waitTimeNS,
                             &downOccurred);
    }
 
@@ -719,6 +734,36 @@ MXUser_TimedDownSemaphore(MXUserSemaphore *sema,  // IN/OUT:
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_TimedDownSemaphore --
+ *
+ *      Perform a down (P; probeer te verlagen; "try to reduce") operation
+ *      on a semaphore with a timeout. The wait time will always have elapsed
+ *      before the routine returns.
+ *
+ *      ALL SUPPORTED PLATFORMS CAN NATIVELY HANDLE MILLISECOND WAITS.
+ *
+ * Results:
+ *      TRUE   Down operation occurred (count has been decremented)
+ *      FALSE  Down operation did not occur (time out occurred)
+ *
+ * Side effects:
+ *      The caller may sleep.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_TimedDownSemaphore(MXUserSemaphore *sema,  // IN/OUT:
+                          uint32 waitTimeMS)      // IN:
+{
+   return MXUser_TimedDownSemaphoreNS(sema,
+                                      (uint64) MXUSER_A_MILLION * waitTimeMS);
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -748,6 +793,7 @@ MXUser_TryDownSemaphore(MXUserSemaphore *sema)  // IN/OUT:
    Bool downOccurred = FALSE;
 
    ASSERT(sema != NULL);
+
    MXUserValidateHeader(&sema->header, MXUSER_TYPE_SEMA);
 
    Atomic_Inc(&sema->activeUserCount);
@@ -799,6 +845,7 @@ MXUser_UpSemaphore(MXUserSemaphore *sema)  // IN/OUT:
    int err;
 
    ASSERT(sema != NULL);
+
    MXUserValidateHeader(&sema->header, MXUSER_TYPE_SEMA);
 
    /*