/* Copyright 2009-2012 The MathWorks, Inc. */ /* This file provides a context-switch aware profiling timer on the Linux and * Windows platforms. */ #if defined(UNIX) && defined(SIL_PROFILING_USE_CGT) /* IF: UNIX and use CGT */ # ifdef __STRICT_ANSI__ /* IF: __STRICT_ANSI__ */ /* 'clock_gettime' is not available in strict ANSI mode on GCC libc. We * have to work this around by temporarily removing the * __STRICT_ANSI__ flag. */ # undef __STRICT_ANSI__ # include # define __STRICT_ANSI__ # else /* ELSE: __STRICT_ANSI__ */ # include # endif /* END: __STRICT_ANSI__ */ # include #endif /* END: UNIX and use CGT */ #if defined(_MSC_VER) && defined(SIL_PROFILING_USE_QTCT) /* IF: use QTCT */ /* We have to tell the compiler to compile for Vista because MEX * compiles for Windows XP (i.e.: WINVER == 0x0500). After this issue is * addressed, the following flag removals and defines should be removed. */ # undef WINVER # define WINVER 0x0600 # undef _WIN32_WINNT # define _WIN32_WINNT WINVER # undef NTDDI_VERSION # define NTDDI_VERSION 0x06000000 # undef _WIN32_IE # define _WIN32_IE WINVER # if WINVER >= 0x0600 /* IF: Is Windows Vista or later */ /* Windows Vista provides a performance counter which accounts for * thread preemption and context switches. Use this counter if the * source is compiled for Windows Vista (or later versions). */ # include # endif /* END: Is Windows Vista or later */ #endif /* END: use QTCT */ #include "host_timer_x86.h" /* We currently have no way of reporting a run-time error back to Matlab. Still, * both CGT (on Linux) and QTCT (on Windows) may return a run-time error code. * In the case of a runtime error, return this 'magic' number: */ #define RT_TIMER_ERROR_VAL 123123123 uint64_T timestamp_x86(void) { #if defined(__GNUC__) /* IF: compiler is GCC */ # if defined(UNIX) && defined(SIL_PROFILING_USE_CGT) /* IF: use CGT */ /* We are compiling for UNIX with POSIX_THREAD_CPUTIME support. Therefore * we can use the 'clock_gettime' function which is accounting for the time * the simulation thread is inactive. */ struct timespec threadTime; /* 'clock_gettime' can fail. If it does fail, this method will return * the RT_TIMER_ERROR_VAL error code. */ if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &threadTime) == 0) { return threadTime.tv_sec * 1000000000 + threadTime.tv_nsec; } else { /* The call to 'clock_gettime' failed. Return the magic value. */ return RT_TIMER_ERROR_VAL; } # else # error Context switch aware timer is not available. # endif /* END: use CGT */ #elif defined(_MSC_VER) /* ELIF: compiler is MSVC */ # if _MSC_VER <= 1200 /* IF: MSVC 6.0 or lower */ __asm rdtsc # else /* ELSE: MSVC > 6.0 */ # if WINVER >= 0x0600 && defined(SIL_PROFILING_USE_QTCT) /* IF: use QTCT */ ULONG64 CycleTime; if (QueryThreadCycleTime(GetCurrentThread(), &CycleTime)) { return (uint32_T)CycleTime; } else { /* The call to 'QueryThreadCycleTime' failed. Return the magic * value. */ return RT_TIMER_ERROR_VAL; } # else /* ELSE: use RDTSC */ # error Context switch aware timer is not available. # endif /* END: use QTCT */ # endif /* END: MSVC > 6.0 */ #else /* ELSE: compiler is unknown */ # error Context switch aware timer is not available. #endif /* END: compiler */ }