forked from Mirrors/openclonk
linux: Use timerfd instead of poll timeouts
parent
acac8a01d4
commit
8036211c30
|
@ -676,6 +676,7 @@ CHECK_INCLUDE_FILE_CXX(execinfo.h HAVE_EXECINFO_H)
|
|||
CHECK_INCLUDE_FILE_CXX(langinfo.h HAVE_LANGINFO_H)
|
||||
CHECK_INCLUDE_FILE_CXX(poll.h HAVE_POLL_H)
|
||||
CHECK_INCLUDE_FILE_CXX(sys/inotify.h HAVE_SYS_INOTIFY_H)
|
||||
CHECK_INCLUDE_FILE_CXX(sys/timerfd.h HAVE_SYS_TIMERFD_H)
|
||||
CHECK_INCLUDE_FILE_CXX(sys/socket.h HAVE_SYS_SOCKET_H)
|
||||
CHECK_INCLUDE_FILE_CXX(sys/file.h HAVE_SYS_FILE_H)
|
||||
if(USE_CONSOLE)
|
||||
|
|
|
@ -103,6 +103,9 @@
|
|||
/* Define to 1 if you have the <sys/syscall.h> header file. */
|
||||
#cmakedefine HAVE_SYS_SYSCALL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/timerfd.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TIMERFD_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TYPES_H 1
|
||||
|
||||
|
|
|
@ -105,6 +105,9 @@
|
|||
/* Define to 1 if you have the <sys/syscall.h> header file. */
|
||||
#undef HAVE_SYS_SYSCALL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/timerfd.h> header file. */
|
||||
#undef HAVE_SYS_TIMERFD_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ AM_CONDITIONAL(MACOSX, [test $osx = true])
|
|||
|
||||
# various used headers
|
||||
dnl the whitespace is there to prevent AC_INCLUDES_DEFAULT
|
||||
AC_CHECK_HEADERS([stdint.h unistd.h poll.h sys/file.h sys/stat.h sys/types.h locale.h sys/socket.h signal.h langinfo.h sys/inotify.h sys/syscall.h], , , [[ ]])
|
||||
AC_CHECK_HEADERS([stdint.h unistd.h poll.h sys/file.h sys/stat.h sys/types.h locale.h sys/socket.h signal.h langinfo.h sys/timerfd.h sys/inotify.h sys/syscall.h], , , [[ ]])
|
||||
# Mingw does not ship with multimon.h
|
||||
AC_CHECK_HEADERS([multimon.h io.h direct.h share.h], [], [], [[#include <windows.h>]])
|
||||
# iconv
|
||||
|
|
|
@ -572,3 +572,114 @@ bool CStdNotifyProc::CheckAndReset()
|
|||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* CStdMultimediaTimerProc */
|
||||
#ifdef STDSCHEDULER_USE_EVENTS
|
||||
int CStdMultimediaTimerProc::iTimePeriod = 0;
|
||||
|
||||
CStdMultimediaTimerProc::CStdMultimediaTimerProc(uint32_t iDelay) :
|
||||
uCriticalTimerDelay(28),
|
||||
idCriticalTimer(0),
|
||||
uCriticalTimerResolution(5),
|
||||
Event(true)
|
||||
{
|
||||
|
||||
if (!iTimePeriod)
|
||||
{
|
||||
// Get resolution caps
|
||||
TIMECAPS tc;
|
||||
timeGetDevCaps(&tc, sizeof(tc));
|
||||
// Establish minimum resolution
|
||||
uCriticalTimerResolution = BoundBy(uCriticalTimerResolution, tc.wPeriodMin, tc.wPeriodMax);
|
||||
timeBeginPeriod(uCriticalTimerResolution);
|
||||
}
|
||||
iTimePeriod++;
|
||||
|
||||
SetDelay(iDelay);
|
||||
|
||||
}
|
||||
|
||||
CStdMultimediaTimerProc::~CStdMultimediaTimerProc()
|
||||
{
|
||||
if (idCriticalTimer)
|
||||
{
|
||||
timeKillEvent(idCriticalTimer);
|
||||
idCriticalTimer = 0;
|
||||
|
||||
iTimePeriod--;
|
||||
if (!iTimePeriod)
|
||||
timeEndPeriod(uCriticalTimerResolution);
|
||||
}
|
||||
}
|
||||
|
||||
void CStdMultimediaTimerProc::SetDelay(uint32_t iDelay)
|
||||
{
|
||||
|
||||
// Kill old timer (of any)
|
||||
if (idCriticalTimer)
|
||||
timeKillEvent(idCriticalTimer);
|
||||
|
||||
// Set critical timer
|
||||
idCriticalTimer=timeSetEvent(
|
||||
uCriticalTimerDelay,uCriticalTimerResolution,
|
||||
(LPTIMECALLBACK) Event.GetEvent(),0,TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
|
||||
|
||||
}
|
||||
|
||||
bool CStdMultimediaTimerProc::CheckAndReset()
|
||||
{
|
||||
if (!Check()) return false;
|
||||
Event.Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_SYS_TIMERFD_H)
|
||||
#include <sys/timerfd.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
CStdMultimediaTimerProc::CStdMultimediaTimerProc(uint32_t iDelay)
|
||||
{
|
||||
// FIXME: Once linux version 2.6.27 is required, use TFD_NONBLOCK and TFD_CLOEXEC
|
||||
fd = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||
if (fd == -1)
|
||||
Log("timerfd_create failed");
|
||||
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
SetDelay(iDelay);
|
||||
}
|
||||
|
||||
CStdMultimediaTimerProc::~CStdMultimediaTimerProc()
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void CStdMultimediaTimerProc::SetDelay(uint32_t inDelay)
|
||||
{
|
||||
struct itimerspec nv, ov;
|
||||
nv.it_interval.tv_sec = inDelay / 1000;
|
||||
nv.it_interval.tv_nsec = (inDelay % 1000) * 1000000;
|
||||
nv.it_value = nv.it_interval;
|
||||
timerfd_settime(fd, 0, &nv, &ov);
|
||||
}
|
||||
|
||||
void CStdMultimediaTimerProc::Set()
|
||||
{
|
||||
struct itimerspec nv, ov;
|
||||
timerfd_gettime(fd, &nv);
|
||||
nv.it_value.tv_sec = 0;
|
||||
nv.it_value.tv_nsec = 1;
|
||||
timerfd_settime(fd, 0, &nv, &ov);
|
||||
}
|
||||
|
||||
bool CStdMultimediaTimerProc::CheckAndReset()
|
||||
{
|
||||
uint64_t n;
|
||||
return read(fd, &n, 8) != -1;
|
||||
}
|
||||
|
||||
void CStdMultimediaTimerProc::GetFDs(std::vector<struct pollfd> & checkfds)
|
||||
{
|
||||
pollfd pfd = { fd, POLLIN, 0 };
|
||||
checkfds.push_back(pfd);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -150,6 +150,55 @@ public:
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef STDSCHEDULER_USE_EVENTS
|
||||
class CStdMultimediaTimerProc : public CStdNotifyProc
|
||||
{
|
||||
public:
|
||||
CStdMultimediaTimerProc(uint32_t iDelay);
|
||||
~CStdMultimediaTimerProc();
|
||||
|
||||
private:
|
||||
static int iTimePeriod;
|
||||
uint32_t uCriticalTimerDelay;
|
||||
|
||||
UINT idCriticalTimer,uCriticalTimerResolution;
|
||||
CStdEvent Event;
|
||||
bool Check() { return Event.WaitFor(0); }
|
||||
|
||||
public:
|
||||
|
||||
void SetDelay(uint32_t iDelay);
|
||||
void Set() { Event.Set(); }
|
||||
bool CheckAndReset();
|
||||
|
||||
// StdSchedulerProc overrides
|
||||
virtual HANDLE GetEvent() { return Event.GetEvent(); }
|
||||
|
||||
};
|
||||
|
||||
#elif defined(HAVE_SYS_TIMERFD_H)
|
||||
// timer proc using a timerfd
|
||||
class CStdMultimediaTimerProc : public StdSchedulerProc
|
||||
{
|
||||
public:
|
||||
CStdMultimediaTimerProc(uint32_t iDelay);
|
||||
~CStdMultimediaTimerProc();
|
||||
|
||||
private:
|
||||
int fd;
|
||||
|
||||
public:
|
||||
void Set();
|
||||
void SetDelay(uint32_t inDelay);
|
||||
bool CheckAndReset();
|
||||
// StdSchedulerProc overrides
|
||||
virtual void GetFDs(std::vector<struct pollfd> & checkfds);
|
||||
};
|
||||
|
||||
#else
|
||||
#define CStdMultimediaTimerProc CStdTimerProc
|
||||
#endif
|
||||
|
||||
// A simple process scheduler
|
||||
class StdScheduler
|
||||
{
|
||||
|
|
|
@ -217,66 +217,6 @@ void CStdWindow::EnumerateMultiSamples(std::vector<int>& samples) const
|
|||
#endif
|
||||
}
|
||||
|
||||
/* CStdTimerProc */
|
||||
|
||||
int CStdMultimediaTimerProc::iTimePeriod = 0;
|
||||
|
||||
CStdMultimediaTimerProc::CStdMultimediaTimerProc(uint32_t iDelay) :
|
||||
uCriticalTimerDelay(28),
|
||||
idCriticalTimer(0),
|
||||
uCriticalTimerResolution(5),
|
||||
Event(true)
|
||||
{
|
||||
|
||||
if (!iTimePeriod)
|
||||
{
|
||||
// Get resolution caps
|
||||
TIMECAPS tc;
|
||||
timeGetDevCaps(&tc, sizeof(tc));
|
||||
// Establish minimum resolution
|
||||
uCriticalTimerResolution = BoundBy(uCriticalTimerResolution, tc.wPeriodMin, tc.wPeriodMax);
|
||||
timeBeginPeriod(uCriticalTimerResolution);
|
||||
}
|
||||
iTimePeriod++;
|
||||
|
||||
SetDelay(iDelay);
|
||||
|
||||
}
|
||||
|
||||
CStdMultimediaTimerProc::~CStdMultimediaTimerProc()
|
||||
{
|
||||
if (idCriticalTimer)
|
||||
{
|
||||
timeKillEvent(idCriticalTimer);
|
||||
idCriticalTimer = 0;
|
||||
|
||||
iTimePeriod--;
|
||||
if (!iTimePeriod)
|
||||
timeEndPeriod(uCriticalTimerResolution);
|
||||
}
|
||||
}
|
||||
|
||||
void CStdMultimediaTimerProc::SetDelay(uint32_t iDelay)
|
||||
{
|
||||
|
||||
// Kill old timer (of any)
|
||||
if (idCriticalTimer)
|
||||
timeKillEvent(idCriticalTimer);
|
||||
|
||||
// Set critical timer
|
||||
idCriticalTimer=timeSetEvent(
|
||||
uCriticalTimerDelay,uCriticalTimerResolution,
|
||||
(LPTIMECALLBACK) Event.GetEvent(),0,TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
|
||||
|
||||
}
|
||||
|
||||
bool CStdMultimediaTimerProc::CheckAndReset()
|
||||
{
|
||||
if (!Check()) return false;
|
||||
Event.Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* CStdMessageProc */
|
||||
|
||||
bool CStdMessageProc::Execute(int iTimeout, pollfd *)
|
||||
|
|
|
@ -369,31 +369,6 @@ public:
|
|||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
class CStdMultimediaTimerProc : public CStdNotifyProc
|
||||
{
|
||||
public:
|
||||
CStdMultimediaTimerProc(uint32_t iDelay);
|
||||
~CStdMultimediaTimerProc();
|
||||
|
||||
private:
|
||||
static int iTimePeriod;
|
||||
uint32_t uCriticalTimerDelay;
|
||||
|
||||
UINT idCriticalTimer,uCriticalTimerResolution;
|
||||
CStdEvent Event;
|
||||
|
||||
public:
|
||||
|
||||
void SetDelay(uint32_t iDelay);
|
||||
void Set() { Event.Set(); }
|
||||
bool Check() { return Event.WaitFor(0); }
|
||||
bool CheckAndReset();
|
||||
|
||||
// StdSchedulerProc overrides
|
||||
virtual HANDLE GetEvent() { return Event.GetEvent(); }
|
||||
|
||||
};
|
||||
|
||||
class CStdMessageProc : public StdSchedulerProc
|
||||
{
|
||||
public:
|
||||
|
@ -411,8 +386,6 @@ public:
|
|||
virtual HANDLE GetEvent() { return STDSCHEDULER_EVENT_MESSAGE; }
|
||||
|
||||
};
|
||||
#else
|
||||
#define CStdMultimediaTimerProc CStdTimerProc
|
||||
#endif
|
||||
|
||||
#ifdef USE_CONSOLE
|
||||
|
|
Loading…
Reference in New Issue