2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Timed event scheduler
|
|
|
|
* \date 2005-10-24
|
|
|
|
* \author Norman Feske <norman.feske@genode-labs.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2005-2013 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "tick.h"
|
|
|
|
#include "printf.h"
|
|
|
|
|
|
|
|
static Tick *head = 0; /* head of tick list */
|
|
|
|
static Tick::time now = 0; /* recent time (updated by handle function) */
|
|
|
|
|
|
|
|
void Tick::_enqueue()
|
|
|
|
{
|
|
|
|
/* do not enqueue twice */
|
|
|
|
if (++_active > 1) {
|
|
|
|
// printf("enqueue twice? ticks scheduled=%d\n", ticks_scheduled());
|
|
|
|
_active--;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if ticklist is empty add first element */
|
|
|
|
if (!head) {
|
|
|
|
_next = 0;
|
|
|
|
head = this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if deadline is smaller than any other deadline, put it on the head */
|
|
|
|
if ((int)_deadline - (int)now < (int)head->_deadline - (int)now) {
|
|
|
|
_next = head;
|
|
|
|
head = this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find list element with a higher deadline */
|
|
|
|
Tick *curr = head;
|
|
|
|
while (curr->_next && ((int)curr->_next->_deadline - (int)now < (int)_deadline - (int)now))
|
|
|
|
curr = curr->_next;
|
|
|
|
|
|
|
|
/* if end of list is reached, append new element */
|
|
|
|
if (curr->_next == 0) {
|
|
|
|
curr->_next = this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* insert element in middle of list */
|
|
|
|
_next = curr->_next;
|
|
|
|
curr->_next = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tick::_dequeue()
|
|
|
|
{
|
|
|
|
if (!head) return;
|
|
|
|
|
|
|
|
if (head == this) {
|
|
|
|
head = _next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find predecessor in tick queue */
|
|
|
|
Tick *curr;
|
|
|
|
for (curr = head; curr && (curr->_next != this); curr = curr->_next);
|
|
|
|
|
|
|
|
/* tick is not enqueued */
|
|
|
|
if (!curr) return;
|
|
|
|
|
|
|
|
/* skip us in tick queue */
|
|
|
|
curr->_next = _next;
|
|
|
|
|
|
|
|
_next = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tick::schedule(time period)
|
|
|
|
{
|
|
|
|
_period = period;
|
|
|
|
_deadline = now; /* first deadline is overdue */
|
|
|
|
_enqueue();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Tick::ticks_scheduled()
|
|
|
|
{
|
|
|
|
int num_ticks = 0;
|
|
|
|
printf("now=%d\n", (int)now);
|
|
|
|
for (Tick *curr = head; curr; curr = curr->_next, num_ticks++)
|
|
|
|
printf("ticks_scheduled:\n %d: curr=%p, deadline=%d\n",
|
|
|
|
(int)num_ticks, curr, (int)curr->_deadline);
|
|
|
|
return num_ticks;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tick::handle(time curr_time)
|
|
|
|
{
|
|
|
|
Tick *curr;
|
|
|
|
now = curr_time;
|
|
|
|
|
|
|
|
while ((curr = head) && ((int)head->_deadline - (int)now < 0)) {
|
|
|
|
|
|
|
|
/* remove tick from head of the list */
|
|
|
|
head = curr->_next;
|
|
|
|
|
|
|
|
curr->_next = 0;
|
|
|
|
curr->_active--;
|
|
|
|
|
|
|
|
/* do not reschedule if tick function returns 0 */
|
|
|
|
if (!curr->on_tick()) continue;
|
|
|
|
|
|
|
|
/* schedule next event */
|
|
|
|
if (curr->_deadline == 0)
|
|
|
|
curr->_deadline = now;
|
|
|
|
|
|
|
|
curr->_deadline += curr->_period;
|
|
|
|
curr->_enqueue();
|
|
|
|
}
|
|
|
|
}
|