From: John Wolfe Date: Tue, 22 Dec 2020 20:22:03 +0000 (-0800) Subject: MXUser Semaphores - nanosecond resolution wait times X-Git-Tag: stable-11.3.0~203 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c80f0f3db5df3a055c70949e4c07326f98ac7045;p=thirdparty%2Fopen-vm-tools.git MXUser Semaphores - nanosecond resolution wait times 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. --- diff --git a/open-vm-tools/lib/include/userlock.h b/open-vm-tools/lib/include/userlock.h index 7a6ca5df6..b58b66305 100644 --- a/open-vm-tools/lib/include/userlock.h +++ b/open-vm-tools/lib/include/userlock.h @@ -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, diff --git a/open-vm-tools/lib/lock/ulSema.c b/open-vm-tools/lib/lock/ulSema.c index 904e05b45..aabb087cc 100644 --- a/open-vm-tools/lib/lock/ulSema.c +++ b/open-vm-tools/lib/lock/ulSema.c @@ -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); /*