Robert,
This is a patch to osg::Timer that works around the problem with
QueryPerformanceCounter() on Athlon X2 processors under Windows XP. It's a
documented problem that we've discussed on the list in the past. QPC on
Athlon X2's sometimes returns negative numbers and otherwise erroneous
information depending on the BIOS settings. Here's some background:
http://channel9.msdn.com/ShowPost.aspx?PostID=156175
http://support.microsoft.com/?id=896256 (an alleged fix that didn't work for
me)
The patch simply ensures that QueryPerformanceCounter/Frequency is always
executed on the same logical processor. The changes are localized in #ifdef
ATHLONX2_QPFIX blocks.
Please consider this for inclusion. I'm not well-enough versed in CMake to
configure the #define that way but perhaps that's an option too. Thanks!
This problem has been bugging me for a long time. -gw
--
Glenn Waldron : Pelican Mapping : http://pelicanmapping.com : 703-652-4791
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
//#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <osg/Timer>
#include <osg/Notify>
using namespace osg;
// follows are the constructors of the Timer class, once version
// for each OS combination. The order is WIN32, FreeBSD, Linux, IRIX,
// and the rest of the world.
//
// all the rest of the timer methods are implemented within the header.
Timer* Timer::instance()
{
static Timer s_timer;
return &s_timer;
}
#ifdef WIN32
#include <sys/types.h>
#include <fcntl.h>
#include <windows.h>
#include <winbase.h>
Timer::Timer()
{
LARGE_INTEGER frequency;
#ifdef ATHLONX2_QPFIX
HANDLE curr_thread = GetCurrentThread();
DWORD old_mask = SetThreadAffinityMask( curr_thread, 0x1 );
#endif
BOOL ok = QueryPerformanceFrequency(&frequency);
#ifdef ATHLONX2_QPFIX
SetThreadAffinityMask( curr_thread, old_mask );
#endif
if(ok)
{
_secsPerTick = 1.0/(double)frequency.QuadPart;
}
else
{
_secsPerTick = 1.0;
notify(NOTICE)<<"Error: Timer::Timer() unable to use
QueryPerformanceFrequency, "<<std::endl;
notify(NOTICE)<<"timing code will be wrong, Windows error code:
"<<GetLastError()<<std::endl;
}
setStartTick();
}
Timer_t Timer::tick() const
{
LARGE_INTEGER qpc;
#ifdef ATHLONX2_QPFIX
HANDLE curr_thread = GetCurrentThread();
DWORD old_mask = SetThreadAffinityMask( curr_thread, 0x1 );
#endif
BOOL ok = QueryPerformanceCounter(&qpc);
#ifdef ATHLONX2_QPFIX
SetThreadAffinityMask( curr_thread, old_mask );
#endif
if (ok)
{
return qpc.QuadPart;
}
else
{
notify(NOTICE)<<"Error: Timer::Timer() unable to use
QueryPerformanceCounter, "<<std::endl;
notify(NOTICE)<<"timing code will be wrong, Windows error code:
"<<GetLastError()<<std::endl;
return 0;
}
}
#else
#include <sys/time.h>
Timer::Timer( void )
{
_secsPerTick = (1.0 / (double) 1000000);
setStartTick();
}
Timer_t Timer::tick() const
{
struct timeval tv;
gettimeofday(&tv, NULL);
return ((osg::Timer_t)tv.tv_sec)*1000000+(osg::Timer_t)tv.tv_usec;
}
#endif
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org