genode/repos/os/src/drivers/timer/include_periodic/platform_timer.h

92 lines
1.9 KiB
C++

/*
* \brief Platform timer based on spinning usleep
* \author Norman Feske
* \date 2009-06-16
*/
/*
* Copyright (C) 2009-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _PLATFORM_TIMER_H_
#define _PLATFORM_TIMER_H_
/* Genode inludes */
#include <base/thread.h>
#include <os/server.h>
class Platform_timer
{
private:
Genode::Lock mutable _lock; /* for protecting '_next_timeout_usec' */
unsigned long _next_timeout_usec; /* timeout of current sleep */
unsigned long _curr_time_usec; /* accumulated sleep time */
/**
* Platform-specific sleep implementation
*/
void _usleep(unsigned long usecs);
public:
/**
* Constructor
*/
Platform_timer() : _next_timeout_usec(max_timeout()), _curr_time_usec(0) { }
/**
* Set next relative timeout
*/
void schedule_timeout(unsigned long timeout_usec)
{
Genode::Lock::Guard lock_guard(_lock);
_next_timeout_usec = timeout_usec;
}
/**
* Return maximum supported timeout in microseconds
*/
unsigned long max_timeout();
/**
* Get current time in microseconds
*/
unsigned long curr_time() const;
/**
* Block until the scheduled timeout triggers
*/
void wait_for_timeout(Genode::Thread_base *blocking_thread)
{
enum { SLEEP_GRANULARITY_USEC = 1000UL };
unsigned long last_time = curr_time();
_lock.lock();
while (_next_timeout_usec) {
_lock.unlock();
try { _usleep(SLEEP_GRANULARITY_USEC); }
catch (Genode::Blocking_canceled) { }
unsigned long now_time = curr_time();
unsigned long sleep_duration = now_time - last_time;
last_time = now_time;
_lock.lock();
if (_next_timeout_usec >= sleep_duration)
_next_timeout_usec -= sleep_duration;
else
break;
}
_lock.unlock();
}
};
#endif /* _PLATFORM_TIMER_H_ */