1 /* The kernel call implemented in this file:
2 * m_type: SYS_SETALARM
3 *
4 * The parameters for this kernel call are:
5 * m_lsys_krn_sys_setalarm.exp_time (alarm's expiration time)
6 * m_lsys_krn_sys_setalarm.abs_time (expiration time is absolute?)
7 * m_lsys_krn_sys_setalarm.time_left (return seconds left of previous)
8 */
9
10 #include "kernel/system.h"
11
12 #include <minix/endpoint.h>
13 #include <assert.h>
14
15 #if USE_SETALARM
16
17 static void cause_alarm(int proc_nr_e);
18
19 /*===========================================================================*
20 * do_setalarm *
21 *===========================================================================*/
do_setalarm(struct proc * caller,message * m_ptr)22 int do_setalarm(struct proc * caller, message * m_ptr)
23 {
24 /* A process requests a synchronous alarm, or wants to cancel its alarm. */
25 long exp_time; /* expiration time for this alarm */
26 int use_abs_time; /* use absolute or relative time */
27 minix_timer_t *tp; /* the process' timer structure */
28 clock_t uptime; /* placeholder for current uptime */
29
30 /* Extract shared parameters from the request message. */
31 exp_time = m_ptr->m_lsys_krn_sys_setalarm.exp_time;
32 use_abs_time = m_ptr->m_lsys_krn_sys_setalarm.abs_time;
33 if (! (priv(caller)->s_flags & SYS_PROC)) return(EPERM);
34
35 /* Get the timer structure and set the parameters for this alarm. */
36 tp = &(priv(caller)->s_alarm_timer);
37
38 /* Return the ticks left on the previous alarm. */
39 uptime = get_monotonic();
40 if (!tmr_is_set(tp)) {
41 m_ptr->m_lsys_krn_sys_setalarm.time_left = TMR_NEVER;
42 } else if (tmr_is_first(uptime, tp->tmr_exp_time)) {
43 m_ptr->m_lsys_krn_sys_setalarm.time_left = tp->tmr_exp_time - uptime;
44 } else {
45 m_ptr->m_lsys_krn_sys_setalarm.time_left = 0;
46 }
47
48 /* For the caller's convenience, also return the current time. */
49 m_ptr->m_lsys_krn_sys_setalarm.uptime = uptime;
50
51 /*
52 * Finally, (re)set the timer depending on the expiration time. Note that
53 * an absolute time of zero is as valid as any other absolute value, so only
54 * a relative time value of zero resets the timer.
55 */
56 if (!use_abs_time && exp_time == 0) {
57 reset_kernel_timer(tp);
58 } else {
59 if (!use_abs_time)
60 exp_time += uptime;
61 set_kernel_timer(tp, exp_time, cause_alarm, caller->p_endpoint);
62 }
63 return(OK);
64 }
65
66 /*===========================================================================*
67 * cause_alarm *
68 *===========================================================================*/
cause_alarm(int proc_nr_e)69 static void cause_alarm(int proc_nr_e)
70 {
71 /* Routine called if a timer goes off and the process requested a synchronous
72 * alarm. The process number is stored as the timer argument. Notify that
73 * process with a notification message from CLOCK.
74 */
75 mini_notify(proc_addr(CLOCK), proc_nr_e); /* notify process */
76 }
77
78 #endif /* USE_SETALARM */
79