1 /* The kernel call implemented in this file:
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)
11 #include "kernel/system.h"
14 #include <minix/endpoint.h>
18 /*===========================================================================*
20 *===========================================================================*/
21 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
)
36 /* The target process must be valid. */
37 proc_nr_e
= (m_ptr
->VT_ENDPT
== SELF
) ? caller
->p_endpoint
: 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
) {
61 rp
->p_misc_flags
&= ~pt_flag
; /* disable virtual timer */
63 if (m_ptr
->VT_VALUE
> 0) {
64 *pt_left
= m_ptr
->VT_VALUE
; /* set new timer value */
65 rp
->p_misc_flags
|= pt_flag
; /* (re)enable virtual timer */
67 *pt_left
= 0; /* clear timer value */
71 m_ptr
->VT_VALUE
= old_value
;
76 #endif /* USE_VTIMER */
78 /*===========================================================================*
80 *===========================================================================*/
81 void vtimer_check(struct proc
* rp
)
83 /* This is called from the clock task, so we can be interrupted by the clock
84 * interrupt, but not by the system task. Therefore we only have to protect
85 * against interference from the clock handler. We can safely perform the
86 * following actions without locking as well though, as the clock handler
87 * never alters p_misc_flags, and only decreases p_virt_left/p_prof_left.
90 /* Check if the virtual timer expired. If so, send a SIGVTALRM signal. */
91 if ((rp
->p_misc_flags
& MF_VIRT_TIMER
) && rp
->p_virt_left
== 0) {
92 rp
->p_misc_flags
&= ~MF_VIRT_TIMER
;
94 cause_sig(rp
->p_nr
, SIGVTALRM
);
97 /* Check if the profile timer expired. If so, send a SIGPROF signal. */
98 if ((rp
->p_misc_flags
& MF_PROF_TIMER
) && rp
->p_prof_left
== 0) {
99 rp
->p_misc_flags
&= ~MF_PROF_TIMER
;
101 cause_sig(rp
->p_nr
, SIGPROF
);