xref: /minix3/minix/kernel/system/do_setalarm.c (revision cfd712b4245f67a5631cc14e950ce43b18455602)
1433d6423SLionel Sambuc /* The kernel call implemented in this file:
2433d6423SLionel Sambuc  *   m_type:	SYS_SETALARM
3433d6423SLionel Sambuc  *
4433d6423SLionel Sambuc  * The parameters for this kernel call are:
5433d6423SLionel Sambuc  *    m_lsys_krn_sys_setalarm.exp_time		(alarm's expiration time)
6433d6423SLionel Sambuc  *    m_lsys_krn_sys_setalarm.abs_time		(expiration time is absolute?)
7433d6423SLionel Sambuc  *    m_lsys_krn_sys_setalarm.time_left		(return seconds left of previous)
8433d6423SLionel Sambuc  */
9433d6423SLionel Sambuc 
10433d6423SLionel Sambuc #include "kernel/system.h"
11433d6423SLionel Sambuc 
12433d6423SLionel Sambuc #include <minix/endpoint.h>
13433d6423SLionel Sambuc #include <assert.h>
14433d6423SLionel Sambuc 
15433d6423SLionel Sambuc #if USE_SETALARM
16433d6423SLionel Sambuc 
17*cfd712b4SDavid van Moolenbroek static void cause_alarm(int proc_nr_e);
18433d6423SLionel Sambuc 
19433d6423SLionel Sambuc /*===========================================================================*
20433d6423SLionel Sambuc  *				do_setalarm				     *
21433d6423SLionel Sambuc  *===========================================================================*/
do_setalarm(struct proc * caller,message * m_ptr)22433d6423SLionel Sambuc int do_setalarm(struct proc * caller, message * m_ptr)
23433d6423SLionel Sambuc {
24433d6423SLionel Sambuc /* A process requests a synchronous alarm, or wants to cancel its alarm. */
25433d6423SLionel Sambuc   long exp_time;		/* expiration time for this alarm */
26433d6423SLionel Sambuc   int use_abs_time;		/* use absolute or relative time */
27433d6423SLionel Sambuc   minix_timer_t *tp;		/* the process' timer structure */
28433d6423SLionel Sambuc   clock_t uptime;		/* placeholder for current uptime */
29433d6423SLionel Sambuc 
30433d6423SLionel Sambuc   /* Extract shared parameters from the request message. */
31*cfd712b4SDavid van Moolenbroek   exp_time = m_ptr->m_lsys_krn_sys_setalarm.exp_time;
32*cfd712b4SDavid van Moolenbroek   use_abs_time = m_ptr->m_lsys_krn_sys_setalarm.abs_time;
33433d6423SLionel Sambuc   if (! (priv(caller)->s_flags & SYS_PROC)) return(EPERM);
34433d6423SLionel Sambuc 
35433d6423SLionel Sambuc   /* Get the timer structure and set the parameters for this alarm. */
36433d6423SLionel Sambuc   tp = &(priv(caller)->s_alarm_timer);
37433d6423SLionel Sambuc 
38433d6423SLionel Sambuc   /* Return the ticks left on the previous alarm. */
39433d6423SLionel Sambuc   uptime = get_monotonic();
40*cfd712b4SDavid van Moolenbroek   if (!tmr_is_set(tp)) {
41e10ce184SDavid van Moolenbroek 	m_ptr->m_lsys_krn_sys_setalarm.time_left = TMR_NEVER;
42*cfd712b4SDavid van Moolenbroek   } else if (tmr_is_first(uptime, tp->tmr_exp_time)) {
43*cfd712b4SDavid van Moolenbroek 	m_ptr->m_lsys_krn_sys_setalarm.time_left = tp->tmr_exp_time - uptime;
44433d6423SLionel Sambuc   } else {
45433d6423SLionel Sambuc 	m_ptr->m_lsys_krn_sys_setalarm.time_left = 0;
46433d6423SLionel Sambuc   }
47433d6423SLionel Sambuc 
48e10ce184SDavid van Moolenbroek   /* For the caller's convenience, also return the current time. */
49e10ce184SDavid van Moolenbroek   m_ptr->m_lsys_krn_sys_setalarm.uptime = uptime;
50e10ce184SDavid van Moolenbroek 
51*cfd712b4SDavid van Moolenbroek   /*
52*cfd712b4SDavid van Moolenbroek    * Finally, (re)set the timer depending on the expiration time.  Note that
53*cfd712b4SDavid van Moolenbroek    * an absolute time of zero is as valid as any other absolute value, so only
54*cfd712b4SDavid van Moolenbroek    * a relative time value of zero resets the timer.
55*cfd712b4SDavid van Moolenbroek    */
56*cfd712b4SDavid van Moolenbroek   if (!use_abs_time && exp_time == 0) {
57433d6423SLionel Sambuc 	reset_kernel_timer(tp);
58433d6423SLionel Sambuc   } else {
59*cfd712b4SDavid van Moolenbroek 	if (!use_abs_time)
60*cfd712b4SDavid van Moolenbroek 		exp_time += uptime;
61*cfd712b4SDavid van Moolenbroek 	set_kernel_timer(tp, exp_time, cause_alarm, caller->p_endpoint);
62433d6423SLionel Sambuc   }
63433d6423SLionel Sambuc   return(OK);
64433d6423SLionel Sambuc }
65433d6423SLionel Sambuc 
66433d6423SLionel Sambuc /*===========================================================================*
67433d6423SLionel Sambuc  *				cause_alarm				     *
68433d6423SLionel Sambuc  *===========================================================================*/
cause_alarm(int proc_nr_e)69*cfd712b4SDavid van Moolenbroek static void cause_alarm(int proc_nr_e)
70433d6423SLionel Sambuc {
71433d6423SLionel Sambuc /* Routine called if a timer goes off and the process requested a synchronous
72*cfd712b4SDavid van Moolenbroek  * alarm. The process number is stored as the timer argument. Notify that
73433d6423SLionel Sambuc  * process with a notification message from CLOCK.
74433d6423SLionel Sambuc  */
75433d6423SLionel Sambuc   mini_notify(proc_addr(CLOCK), proc_nr_e);	/* notify process */
76433d6423SLionel Sambuc }
77433d6423SLionel Sambuc 
78433d6423SLionel Sambuc #endif /* USE_SETALARM */
79