1433d6423SLionel Sambuc #include "sysutil.h"
2433d6423SLionel Sambuc #include <minix/timers.h>
3433d6423SLionel Sambuc
4433d6423SLionel Sambuc /*===========================================================================*
5433d6423SLionel Sambuc * tickdelay *
6433d6423SLionel Sambuc *===========================================================================*/
tickdelay(clock_t ticks)7433d6423SLionel Sambuc int tickdelay(clock_t ticks)
8433d6423SLionel Sambuc {
9433d6423SLionel Sambuc /* This function uses the synchronous alarm to delay for a while. This works
10433d6423SLionel Sambuc * even if a previous synchronous alarm was scheduled, because the remaining
11*e10ce184SDavid van Moolenbroek * ticks of the previous alarm are returned so that it can be rescheduled.
12*e10ce184SDavid van Moolenbroek * Note however that a long tick delay (longer than the remaining time of the
13433d6423SLionel Sambuc * previous) alarm will also delay the previous alarm.
14433d6423SLionel Sambuc */
15*e10ce184SDavid van Moolenbroek clock_t time_left, uptime;
16*e10ce184SDavid van Moolenbroek message m;
17*e10ce184SDavid van Moolenbroek int r, status;
18433d6423SLionel Sambuc
19433d6423SLionel Sambuc if (ticks <= 0) return OK; /* check for robustness */
20433d6423SLionel Sambuc
21*e10ce184SDavid van Moolenbroek /* Set the new alarm while getting the time left on the previous alarm. */
22*e10ce184SDavid van Moolenbroek if ((r = sys_setalarm2(ticks, FALSE, &time_left, &uptime)) != OK)
23*e10ce184SDavid van Moolenbroek return r;
24433d6423SLionel Sambuc
25*e10ce184SDavid van Moolenbroek /* Await synchronous alarm. Since an alarm notification may already have
26*e10ce184SDavid van Moolenbroek * been dispatched by the time that we set the new alarm, we keep going
27*e10ce184SDavid van Moolenbroek * until we actually receive an alarm with a timestamp no earlier than the
28*e10ce184SDavid van Moolenbroek * alarm time we expect.
29*e10ce184SDavid van Moolenbroek */
30*e10ce184SDavid van Moolenbroek while ((r = ipc_receive(CLOCK, &m, &status)) == OK) {
31*e10ce184SDavid van Moolenbroek if (m.m_type == NOTIFY_MESSAGE &&
32*e10ce184SDavid van Moolenbroek m.m_notify.timestamp >= uptime + ticks)
33*e10ce184SDavid van Moolenbroek break;
34433d6423SLionel Sambuc }
35433d6423SLionel Sambuc
36*e10ce184SDavid van Moolenbroek /* Check if we must reschedule the previous alarm. */
37*e10ce184SDavid van Moolenbroek if (time_left != TMR_NEVER) {
38*e10ce184SDavid van Moolenbroek if (time_left > ticks)
39*e10ce184SDavid van Moolenbroek time_left -= ticks;
40*e10ce184SDavid van Moolenbroek else
41*e10ce184SDavid van Moolenbroek time_left = 1; /* force an alarm */
42*e10ce184SDavid van Moolenbroek
43*e10ce184SDavid van Moolenbroek /* There's no point in returning an error from here.. */
44*e10ce184SDavid van Moolenbroek (void)sys_setalarm(time_left, FALSE);
45*e10ce184SDavid van Moolenbroek }
46*e10ce184SDavid van Moolenbroek
47*e10ce184SDavid van Moolenbroek return r;
48433d6423SLionel Sambuc }
49