panic() cleanup.
[minix.git] / kernel / system / do_vtimer.c
bloba85cf3b5aba7c0fbf72b850bc2b7c5dc6ed6ba23
1 /* The kernel call implemented in this file:
2 * m_type: SYS_VTIMER
4 * The parameters for this kernel call are:
5 * m2_i1: VT_WHICH (the timer: VT_VIRTUAL or VT_PROF)
6 * m2_i2: VT_SET (whether to set, or just retrieve)
7 * m2_l1: VT_VALUE (new/old expiration time, in ticks)
8 * m2_l2: VT_ENDPT (process to which the timer belongs)
9 */
11 #include "../system.h"
13 #include <signal.h>
14 #include <minix/endpoint.h>
16 #if USE_VTIMER
18 /*===========================================================================*
19 * do_vtimer *
20 *===========================================================================*/
21 PUBLIC int do_vtimer(struct proc * caller, message * m_ptr)
23 /* Set and/or retrieve the value of one of a process' virtual timers. */
24 struct proc *rp; /* pointer to process the timer belongs to */
25 register int pt_flag; /* the misc on/off flag for the req.d timer */
26 register clock_t *pt_left; /* pointer to the process' ticks-left field */
27 clock_t old_value; /* the previous number of ticks left */
28 int proc_nr, proc_nr_e;
30 /* The requesting process must be privileged. */
31 if (! (priv(caller)->s_flags & SYS_PROC)) return(EPERM);
33 if (m_ptr->VT_WHICH != VT_VIRTUAL && m_ptr->VT_WHICH != VT_PROF)
34 return(EINVAL);
36 /* The target process must be valid. */
37 proc_nr_e = (m_ptr->VT_ENDPT == SELF) ? m_ptr->m_source : m_ptr->VT_ENDPT;
38 if (!isokendpt(proc_nr_e, &proc_nr)) return(EINVAL);
39 rp = proc_addr(proc_nr);
41 /* Determine which flag and which field in the proc structure we want to
42 * retrieve and/or modify. This saves us having to differentiate between
43 * VT_VIRTUAL and VT_PROF multiple times below.
45 if (m_ptr->VT_WHICH == VT_VIRTUAL) {
46 pt_flag = MF_VIRT_TIMER;
47 pt_left = &rp->p_virt_left;
48 } else { /* VT_PROF */
49 pt_flag = MF_PROF_TIMER;
50 pt_left = &rp->p_prof_left;
53 /* Retrieve the old value. */
54 if (rp->p_misc_flags & pt_flag) {
55 old_value = *pt_left;
57 if (old_value < 0) old_value = 0;
58 } else {
59 old_value = 0;
62 /* Set the new value, if requested. This is called from the system task, so
63 * we can be interrupted by the clock interrupt, but not by the clock task.
64 * Therefore we only have to protect against interference from clock.c's
65 * clock_handler(). We can do this without disabling interrupts, by removing
66 * the timer's flag before changing the ticks-left field; in that case the
67 * clock interrupt will not touch the latter anymore.
69 if (m_ptr->VT_SET) {
70 rp->p_misc_flags &= ~pt_flag; /* disable virtual timer */
72 if (m_ptr->VT_VALUE > 0) {
73 *pt_left = m_ptr->VT_VALUE; /* set new timer value */
74 rp->p_misc_flags |= pt_flag; /* (re)enable virtual timer */
75 } else {
76 *pt_left = 0; /* clear timer value */
80 m_ptr->VT_VALUE = old_value;
82 return(OK);
85 #endif /* USE_VTIMER */
87 /*===========================================================================*
88 * vtimer_check *
89 *===========================================================================*/
90 PUBLIC void vtimer_check(rp)
91 struct proc *rp; /* pointer to the process */
93 /* This is called from the clock task, so we can be interrupted by the clock
94 * interrupt, but not by the system task. Therefore we only have to protect
95 * against interference from the clock handler. We can safely perform the
96 * following actions without locking as well though, as the clock handler
97 * never alters p_misc_flags, and only decreases p_virt_left/p_prof_left.
100 /* Check if the virtual timer expired. If so, send a SIGVTALRM signal. */
101 if ((rp->p_misc_flags & MF_VIRT_TIMER) && rp->p_virt_left <= 0) {
102 rp->p_misc_flags &= ~MF_VIRT_TIMER;
103 rp->p_virt_left = 0;
104 cause_sig(rp->p_nr, SIGVTALRM);
107 /* Check if the profile timer expired. If so, send a SIGPROF signal. */
108 if ((rp->p_misc_flags & MF_PROF_TIMER) && rp->p_prof_left <= 0) {
109 rp->p_misc_flags &= ~MF_PROF_TIMER;
110 rp->p_prof_left = 0;
111 cause_sig(rp->p_nr, SIGPROF);