xref: /minix/minix/lib/libsys/tickdelay.c (revision 9f988b79)
1 #include "sysutil.h"
2 #include <minix/timers.h>
3 
4 /*===========================================================================*
5  *                               tickdelay			    	     *
6  *===========================================================================*/
7 int tickdelay(clock_t ticks)
8 {
9 /* This function uses the synchronous alarm to delay for a while. This works
10  * even if a previous synchronous alarm was scheduled, because the remaining
11  * ticks of the previous alarm are returned so that it can be rescheduled.
12  * Note however that a long tick delay (longer than the remaining time of the
13  * previous) alarm will also delay the previous alarm.
14  */
15     clock_t time_left, uptime;
16     message m;
17     int r, status;
18 
19     if (ticks <= 0) return OK;		/* check for robustness */
20 
21     /* Set the new alarm while getting the time left on the previous alarm. */
22     if ((r = sys_setalarm2(ticks, FALSE, &time_left, &uptime)) != OK)
23 	return r;
24 
25     /* Await synchronous alarm.  Since an alarm notification may already have
26      * been dispatched by the time that we set the new alarm, we keep going
27      * until we actually receive an alarm with a timestamp no earlier than the
28      * alarm time we expect.
29      */
30     while ((r = ipc_receive(CLOCK, &m, &status)) == OK) {
31 	if (m.m_type == NOTIFY_MESSAGE &&
32 	    m.m_notify.timestamp >= uptime + ticks)
33 		break;
34     }
35 
36     /* Check if we must reschedule the previous alarm. */
37     if (time_left != TMR_NEVER) {
38 	if (time_left > ticks)
39 		time_left -= ticks;
40 	else
41 		time_left = 1; /* force an alarm */
42 
43 	/* There's no point in returning an error from here.. */
44 	(void)sys_setalarm(time_left, FALSE);
45     }
46 
47     return r;
48 }
49