diff options
Diffstat (limited to 'src/pal/src/thread/thread.cpp')
-rw-r--r-- | src/pal/src/thread/thread.cpp | 237 |
1 files changed, 166 insertions, 71 deletions
diff --git a/src/pal/src/thread/thread.cpp b/src/pal/src/thread/thread.cpp index 73504a90ef..69466ecc04 100644 --- a/src/pal/src/thread/thread.cpp +++ b/src/pal/src/thread/thread.cpp @@ -1303,37 +1303,24 @@ InternalSetThreadPriorityExit: return palError; } -/*++ -Function: - GetThreadTimes - -See MSDN doc. ---*/ BOOL -PALAPI -GetThreadTimes( - IN HANDLE hThread, - OUT LPFILETIME lpCreationTime, - OUT LPFILETIME lpExitTime, - OUT LPFILETIME lpKernelTime, - OUT LPFILETIME lpUserTime) +CorUnix::GetThreadTimesInternal( + IN HANDLE hThread, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime) { - PERF_ENTRY(GetThreadTimes); - ENTRY("GetThreadTimes(hThread=%p, lpExitTime=%p, lpKernelTime=%p," - "lpUserTime=%p)\n", - hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime ); - + __int64 calcTime; BOOL retval = FALSE; - + const __int64 SECS_TO_NS = 1000000000; /* 10^9 */ + #if HAVE_MACH_THREADS + thread_basic_info resUsage; PAL_ERROR palError = NO_ERROR; - CPalThread *pthrCurrent = NULL; + CPalThread *pthrCurrent = NULL; CPalThread *pthrTarget = NULL; IPalObject *pobjThread = NULL; - thread_basic_info resUsage; mach_msg_type_number_t resUsage_count = THREAD_BASIC_INFO_COUNT; - __int64 calcTime; - const __int64 SECS_TO_NS = 1000000000; /* 10^9 */ + const __int64 USECS_TO_NS = 1000; /* 10^3 */ pthrCurrent = InternalGetCurrentThread(); @@ -1345,82 +1332,190 @@ GetThreadTimes( &pobjThread ); - if (palError != NO_ERROR) + if (palError != NO_ERROR) { ASSERT("Unable to get thread data from handle %p" "thread\n", hThread); SetLastError(ERROR_INTERNAL_ERROR); - goto GetThreadTimesExit; - } + goto SetTimesToZero; + } pthrTarget->Lock(pthrCurrent); - + mach_port_t mhThread; - mhThread = pthrTarget->GetMachPortSelf(); - - kern_return_t status; - status = thread_info( - mhThread, - THREAD_BASIC_INFO, - (thread_info_t)&resUsage, - &resUsage_count); - + mhThread = pthread_mach_thread_np(pthrTarget->GetPThreadSelf()); + + kern_return_t status; + status = thread_info( + mhThread, + THREAD_BASIC_INFO, + (thread_info_t)&resUsage, + &resUsage_count); + + pthrTarget->Unlock(pthrCurrent); + if (status != KERN_SUCCESS) - { + { ASSERT("Unable to get resource usage information for the current " "thread\n"); SetLastError(ERROR_INTERNAL_ERROR); - goto GetThreadTimesExit; + goto SetTimesToZero; } + + /* Get the time of user mode execution, in nanoseconds */ + calcTime = (__int64)resUsage.user_time.seconds * SECS_TO_NS; + calcTime += (__int64)resUsage.user_time.microseconds * USECS_TO_NS; + /* Assign the time into lpUserTime */ + lpUserTime->dwLowDateTime = (DWORD)calcTime; + lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); + + /* Get the time of kernel mode execution, in nanoseconds */ + calcTime = (__int64)resUsage.system_time.seconds * SECS_TO_NS; + calcTime += (__int64)resUsage.system_time.microseconds * USECS_TO_NS; + /* Assign the time into lpKernelTime */ + lpKernelTime->dwLowDateTime = (DWORD)calcTime; + lpKernelTime->dwHighDateTime = (DWORD)(calcTime >> 32); + + retval = TRUE; + + goto GetThreadTimesInternalExit; + +#else //HAVE_MACH_THREADS + + PAL_ERROR palError; + CPalThread *pThread; + CPalThread *pTargetThread; + IPalObject *pobjThread = NULL; + clockid_t cid; + + pThread = InternalGetCurrentThread(); + + palError = InternalGetThreadDataFromHandle( + pThread, + hThread, + 0, // THREAD_GET_CONTEXT + &pTargetThread, + &pobjThread + ); + if (palError != NO_ERROR) + { + ASSERT("Unable to get thread data from handle %p" + "thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + goto SetTimesToZero; + } + + pTargetThread->Lock(pThread); + + if (pthread_getcpuclockid(pTargetThread->GetPThreadSelf(), &cid) != 0) + { + ASSERT("Unable to get clock from thread\n", hThread); + SetLastError(ERROR_INTERNAL_ERROR); + pTargetThread->Unlock(pThread); + goto SetTimesToZero; + } + + struct timespec ts; + if (clock_gettime(cid, &ts) != 0) + { + ASSERT("clock_gettime() failed; errno is %d (%s)\n", errno, strerror(errno)); + SetLastError(ERROR_INTERNAL_ERROR); + pTargetThread->Unlock(pThread); + goto SetTimesToZero; + } + + pTargetThread->Unlock(pThread); + + /* Calculate time in nanoseconds and assign to user time */ + calcTime = (__int64) ts.tv_sec * SECS_TO_NS; + calcTime += (__int64) ts.tv_nsec; + lpUserTime->dwLowDateTime = (DWORD)calcTime; + lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); + /* Set kernel time to zero, for now */ + lpKernelTime->dwLowDateTime = 0; + lpKernelTime->dwHighDateTime = 0; + + retval = TRUE; + goto GetThreadTimesInternalExit; + +#endif //HAVE_MACH_THREADS + +SetTimesToZero: + + lpUserTime->dwLowDateTime = 0; + lpUserTime->dwHighDateTime = 0; + lpKernelTime->dwLowDateTime = 0; + lpKernelTime->dwHighDateTime = 0; + goto GetThreadTimesInternalExit; + +GetThreadTimesInternalExit: + return retval; +} + +/*++ +Function: + GetThreadTimes + +See MSDN doc. +--*/ +BOOL +PALAPI +GetThreadTimes( + IN HANDLE hThread, + OUT LPFILETIME lpCreationTime, + OUT LPFILETIME lpExitTime, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime) +{ + PERF_ENTRY(GetThreadTimes); + ENTRY("GetThreadTimes(hThread=%p, lpExitTime=%p, lpKernelTime=%p," + "lpUserTime=%p)\n", + hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime ); + + FILETIME KernelTime, UserTime; + + BOOL retval = GetThreadTimesInternal(hThread, &KernelTime, &UserTime); + + /* Not sure if this still needs to be here */ + /* TRACE ("thread_info User: %ld sec,%ld microsec. Kernel: %ld sec,%ld" " microsec\n", resUsage.user_time.seconds, resUsage.user_time.microseconds, resUsage.system_time.seconds, resUsage.system_time.microseconds); + */ + __int64 calcTime; if (lpUserTime) { - /* Get the time of user mode execution, in 100s of nanoseconds */ - calcTime = (__int64)resUsage.user_time.seconds * SECS_TO_NS; - calcTime += (__int64)resUsage.user_time.microseconds * USECS_TO_NS; - calcTime /= 100; /* Produce the time in 100s of ns */ - /* Assign the time into lpUserTime */ + /* Produce the time in 100s of ns */ + calcTime = ((ULONG64)UserTime.dwHighDateTime << 32); + calcTime += (ULONG64)UserTime.dwLowDateTime; + calcTime /= 100; lpUserTime->dwLowDateTime = (DWORD)calcTime; lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); } - if (lpKernelTime) { - /* Get the time of kernel mode execution, in 100s of nanoseconds */ - calcTime = (__int64)resUsage.system_time.seconds * SECS_TO_NS; - calcTime += (__int64)resUsage.system_time.microseconds * USECS_TO_NS; - calcTime /= 100; /* Produce the time in 100s of ns */ - /* Assign the time into lpUserTime */ + /* Produce the time in 100s of ns */ + calcTime = ((ULONG64)KernelTime.dwHighDateTime << 32); + calcTime += (ULONG64)KernelTime.dwLowDateTime; + calcTime /= 100; lpKernelTime->dwLowDateTime = (DWORD)calcTime; lpKernelTime->dwHighDateTime = (DWORD)(calcTime >> 32); } + //Set CreationTime and Exit time to zero for now - maybe change this later? + if (lpCreationTime) + { + lpCreationTime->dwLowDateTime = 0; + lpCreationTime->dwHighDateTime = 0; + } - pthrTarget->Unlock(pthrCurrent); - - retval = TRUE; - -GetThreadTimesExit: - -#else // HAVE_MACH_THREADS - // UNIXTODO: Implement this - lpCreationTime->dwLowDateTime = 0; - lpCreationTime->dwHighDateTime = 0; - - lpExitTime->dwLowDateTime = 0; - lpExitTime->dwHighDateTime = 0; - - lpUserTime->dwLowDateTime = 0; - lpUserTime->dwHighDateTime = 0; - - lpKernelTime->dwLowDateTime = 0; - lpKernelTime->dwHighDateTime = 0; - retval = TRUE; -#endif // HAVE_MACH_THREADS + if (lpExitTime) + { + lpExitTime->dwLowDateTime = 0; + lpExitTime->dwHighDateTime = 0; + } LOGEXIT("GetThreadTimes returns BOOL %d\n", retval); PERF_EXIT(GetThreadTimes); @@ -1666,7 +1761,7 @@ CreateThreadDataExit: /*++ Function: - CreateThreadObject + CreateThreadData Abstract: Creates the IPalObject for a thread, storing |