@@ -450,7 +450,7 @@ namespace CorUnix
450
450
if (dwTimeout != INFINITE)
451
451
{
452
452
// Calculate absolute timeout
453
- palErr = GetAbsoluteTimeout (dwTimeout, &tsAbsTmo);
453
+ palErr = GetAbsoluteTimeout (dwTimeout, &tsAbsTmo, /* fPreferMonotonicClock */ TRUE );
454
454
if (NO_ERROR != palErr)
455
455
{
456
456
ERROR (" Failed to convert timeout to absolute timeout\n " );
@@ -1572,7 +1572,7 @@ namespace CorUnix
1572
1572
ptnwdWorkerThreadNativeData =
1573
1573
&pSynchManager->m_pthrWorker ->synchronizationInfo .m_tnwdNativeData ;
1574
1574
1575
- palErr = GetAbsoluteTimeout (WorkerThreadTerminationTimeout, &tsAbsTmo);
1575
+ palErr = GetAbsoluteTimeout (WorkerThreadTerminationTimeout, &tsAbsTmo, /* fPreferMonotonicClock */ TRUE );
1576
1576
if (NO_ERROR != palErr)
1577
1577
{
1578
1578
ERROR (" Failed to convert timeout to absolute timeout\n " );
@@ -4078,6 +4078,9 @@ namespace CorUnix
4078
4078
int iRet;
4079
4079
const int MaxUnavailableResourceRetries = 10 ;
4080
4080
int iEagains;
4081
+ pthread_condattr_t attrs;
4082
+ pthread_condattr_t *attrsPtr = nullptr ;
4083
+
4081
4084
m_shridWaitAwakened = RawSharedObjectAlloc (sizeof (DWORD),
4082
4085
DefaultSharedPool);
4083
4086
if (NULLSharedID == m_shridWaitAwakened)
@@ -4096,6 +4099,36 @@ namespace CorUnix
4096
4099
VolatileStore<DWORD>(pdwWaitState, TWS_ACTIVE);
4097
4100
m_tsThreadState = TS_STARTING;
4098
4101
4102
+ #if HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK
4103
+ attrsPtr = &attrs;
4104
+ iRet = pthread_condattr_init (&attrs);
4105
+ if (0 != iRet)
4106
+ {
4107
+ ERROR (" Failed to initialize thread synchronization condition attribute "
4108
+ " [error=%d (%s)]\n " , iRet, strerror (iRet));
4109
+ if (ENOMEM == iRet)
4110
+ {
4111
+ palErr = ERROR_NOT_ENOUGH_MEMORY;
4112
+ }
4113
+ else
4114
+ {
4115
+ palErr = ERROR_INTERNAL_ERROR;
4116
+ }
4117
+ goto IPrC_exit;
4118
+ }
4119
+
4120
+ // Ensure that the pthread_cond_timedwait will use CLOCK_MONOTONIC
4121
+ iRet = pthread_condattr_setclock (&attrs, CLOCK_MONOTONIC);
4122
+ if (0 != iRet)
4123
+ {
4124
+ ERROR (" Failed set thread synchronization condition timed wait clock "
4125
+ " [error=%d (%s)]\n " , iRet, strerror (iRet));
4126
+ palErr = ERROR_INTERNAL_ERROR;
4127
+ pthread_condattr_destroy (&attrs);
4128
+ goto IPrC_exit;
4129
+ }
4130
+ #endif // HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK
4131
+
4099
4132
iEagains = 0 ;
4100
4133
Mutex_retry:
4101
4134
iRet = pthread_mutex_init (&m_tnwdNativeData.mutex , NULL );
@@ -4121,7 +4154,9 @@ namespace CorUnix
4121
4154
4122
4155
iEagains = 0 ;
4123
4156
Cond_retry:
4124
- iRet = pthread_cond_init (&m_tnwdNativeData.cond , NULL );
4157
+
4158
+ iRet = pthread_cond_init (&m_tnwdNativeData.cond , attrsPtr);
4159
+
4125
4160
if (0 != iRet)
4126
4161
{
4127
4162
ERROR (" Failed creating thread synchronization condition "
@@ -4146,6 +4181,10 @@ namespace CorUnix
4146
4181
m_tnwdNativeData.fInitialized = true ;
4147
4182
4148
4183
IPrC_exit:
4184
+ if (attrsPtr != nullptr )
4185
+ {
4186
+ pthread_condattr_destroy (attrsPtr);
4187
+ }
4149
4188
if (NO_ERROR != palErr)
4150
4189
{
4151
4190
m_tsThreadState = TS_FAILED;
@@ -4515,27 +4554,37 @@ namespace CorUnix
4515
4554
4516
4555
Converts a relative timeout to an absolute one.
4517
4556
--*/
4518
- PAL_ERROR CPalSynchronizationManager::GetAbsoluteTimeout (DWORD dwTimeout, struct timespec * ptsAbsTmo)
4557
+ PAL_ERROR CPalSynchronizationManager::GetAbsoluteTimeout (DWORD dwTimeout, struct timespec * ptsAbsTmo, BOOL fPreferMonotonicClock )
4519
4558
{
4520
4559
PAL_ERROR palErr = NO_ERROR;
4521
4560
int iRet;
4522
4561
4523
- #if HAVE_WORKING_CLOCK_GETTIME
4524
- // Not every platform implements a (working) clock_gettime
4525
- iRet = clock_gettime (CLOCK_REALTIME, ptsAbsTmo);
4526
- #elif HAVE_WORKING_GETTIMEOFDAY
4527
- // Not every platform implements a (working) gettimeofday
4528
- struct timeval tv;
4529
- iRet = gettimeofday (&tv, NULL );
4530
- if (0 == iRet)
4562
+ #if HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK
4563
+ if (fPreferMonotonicClock )
4531
4564
{
4532
- ptsAbsTmo->tv_sec = tv.tv_sec ;
4533
- ptsAbsTmo->tv_nsec = tv.tv_usec * tccMicroSecondsToNanoSeconds;
4565
+ iRet = clock_gettime (CLOCK_MONOTONIC, ptsAbsTmo);
4534
4566
}
4567
+ else
4568
+ {
4569
+ #endif
4570
+ #if HAVE_WORKING_CLOCK_GETTIME
4571
+ // Not every platform implements a (working) clock_gettime
4572
+ iRet = clock_gettime (CLOCK_REALTIME, ptsAbsTmo);
4573
+ #elif HAVE_WORKING_GETTIMEOFDAY
4574
+ // Not every platform implements a (working) gettimeofday
4575
+ struct timeval tv;
4576
+ iRet = gettimeofday (&tv, NULL );
4577
+ if (0 == iRet)
4578
+ {
4579
+ ptsAbsTmo->tv_sec = tv.tv_sec ;
4580
+ ptsAbsTmo->tv_nsec = tv.tv_usec * tccMicroSecondsToNanoSeconds;
4581
+ }
4535
4582
#else
4536
- #error "Don't know how to get hi-res current time on this platform"
4583
+ #error "Don't know how to get hi-res current time on this platform"
4537
4584
#endif // HAVE_WORKING_CLOCK_GETTIME, HAVE_WORKING_GETTIMEOFDAY
4538
-
4585
+ #if HAVE_CLOCK_MONOTONIC && HAVE_PTHREAD_CONDATTR_SETCLOCK
4586
+ }
4587
+ #endif
4539
4588
if (0 == iRet)
4540
4589
{
4541
4590
ptsAbsTmo->tv_sec += dwTimeout / tccSecondsToMillieSeconds;
0 commit comments