Support for setitimer(ITIMER_REAL).

This commit is contained in:
David van Moolenbroek 2009-08-15 16:09:32 +00:00
parent 062bb2c1e8
commit d82e260a90
20 changed files with 449 additions and 111 deletions

View file

@ -53,6 +53,7 @@
#define CHROOT 61
#define SETSID 62
#define GETPGRP 63
#define ITIMER 64
/* Posix signal handling. */
#define SIGACTION 71

View file

@ -24,4 +24,19 @@ int gettimeofday(struct timeval *_RESTRICT tp, void *_RESTRICT tzp);
/* Compatibility with other Unix systems */
int settimeofday(const struct timeval *tp, const void *tzp);
/* setitimer/getitimer interface */
struct itimerval
{
struct timeval it_interval;
struct timeval it_value;
};
#define ITIMER_REAL 0
#define ITIMER_VIRTUAL 1 /* Not implemented */
#define ITIMER_PROF 2 /* Not implemented */
int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *_RESTRICT value,
struct itimerval *_RESTRICT ovalue);
#endif /* _SYS__TIME_H */

View file

@ -40,6 +40,7 @@ libc_FILES=" \
_geteuid.c \
_getgid.c \
_getgroups.c \
_getitimer.c \
_getpgrp.c \
_getpid.c \
_getppid.c \
@ -69,6 +70,7 @@ libc_FILES=" \
_rmdir.c \
_select.c \
_setgid.c \
_setitimer.c \
_setsid.c \
_setuid.c \
_sigaction.c \

18
lib/posix/_getitimer.c Normal file
View file

@ -0,0 +1,18 @@
#include <lib.h>
#define getitimer _getitimer
#include <sys/time.h>
/*
* This is the implementation for the function to
* invoke the interval timer retrieval system call.
*/
int getitimer(int which, struct itimerval *value)
{
message m;
m.m1_i1 = which;
m.m1_p1 = NULL; /* only retrieve the timer */
m.m1_p2 = (char *) value;
return _syscall(PM_PROC_NR, ITIMER, &m);
}

24
lib/posix/_setitimer.c Normal file
View file

@ -0,0 +1,24 @@
#include <lib.h>
#define setitimer _setitimer
#include <sys/time.h>
/*
* This is the implementation of the function to
* invoke the interval timer setting system call.
*/
int setitimer(int which, const struct itimerval *_RESTRICT value,
struct itimerval *_RESTRICT ovalue)
{
message m;
/* A null pointer for 'value' would make setitimer behave like getitimer,
* which is not according to the specification, so disallow null pointers.
*/
if (value == NULL) return(EINVAL);
m.m1_i1 = which;
m.m1_p1 = (char *) value;
m.m1_p2 = (char *) ovalue;
return _syscall(PM_PROC_NR, ITIMER, &m);
}

View file

@ -45,6 +45,7 @@ libc_FILES=" \
geteuid.s \
getgid.s \
getgroups.s \
getitimer.s \
getnpid.s \
getnprocnr.s \
getpgrp.s \
@ -86,6 +87,7 @@ libc_FILES=" \
select.s \
seekdir.s \
setgid.s \
setitimer.s \
setsid.s \
setuid.s \
sigaction.s \

7
lib/syscall/getitimer.s Normal file
View file

@ -0,0 +1,7 @@
.sect .text
.extern __getitimer
.define _getitimer
.align 2
_getitimer:
jmp __getitimer

7
lib/syscall/setitimer.s Normal file
View file

@ -0,0 +1,7 @@
.sect .text
.extern __setitimer
.define _setitimer
.align 2
_setitimer:
jmp __setitimer

67
man/man2/getitimer.2 Normal file
View file

@ -0,0 +1,67 @@
.TH GETITIMER 2 "April 14, 2006"
.UC 4
.SH NAME
getitimer, setitimer \- get and set value of interval timer
.SH SYNOPSIS
.nf
.ft B
#include <sys/time.h>
int getitimer(int \fIwhich\fP, struct itimerval *\fIvalue\fP)
.in +5
.ti -5
int setitimer(int \fIwhich\fP, const struct itimerval *\fIvalue\fP, struct itimerval *\fIovalue\fP);
.in -5
.ft R
.fi
.SH DESCRIPTION
.B Getitimer
retrieves the current value of the given interval timer, in \fIvalue\fP.
.PP
.B Setitimer
sets a new value for the given interval timer, as given in \fIvalue\fP, and, if \fIovalue\fP is not set to
.BR NULL ,
stores the old value for the interval timer in \fIovalue\fP.
.PP
For both functions, the \fIwhich\fP parameter indicates which of the interval timers they work on; \fIwhich\fP can have one of the following values:
.PP
.TP 15
.B ITIMER_REAL
A timer that is decremented in realtime. When it expires, a
.BR SIGARLM
signal is delivered to the process.
.TP
.B ITIMER_VIRTUAL
Not supported on Minix.
.TP
.B ITIMER_PROF
Not supported on Minix.
.PP
The specified timer will first expire after the time specified in the 'it_value' field of the itimerval structure. Similarly, upon retrieval the 'it_value' field will contain the time after which the timer will expire.
.PP
If 'it_value' is zero, then the timer is disabled, and the 'it_interval' field is ignored and (upon retrieval) set to zero. Otherwise, 'it_interval' contains the repetition interval after which the timer will repeatedly expire, starting from the moment that the timer expires for the first time according to the 'it_value' value. If 'it_interval' is set to zero, no repetition will occur.
.PP
The maximum supported timeout value that
.B setitimer
accepts, depends on the clock tick rate of the operating system.
.PP
These functions share their real-time timer with
.BR alarm (2).
Therefore, use of both types of functions in one program yields undefined results.
.SH RETURN VALUES
Upon successful completion, these functions return 0. Otherwise, a value of -1 is returned and \fIerrno\fP is set to indicate the error.
.SH ERRORS
The functions will fail if any of the following occur:
.TP 15
.B EINVAL
Either \fIwhich\fP is not one of the ITIMER_* constants above, or one of the timeval structures in \fIvalue\fP contains a bad or too large value.
.TP
.B EFAULT
Bad \fIvalue\fP or \fIovalue\fP address.
.TP
.B ENOSYS
The value of \fIwhich\fP is not ITIMER_REAL.
.SH SEE ALSO
.BR alarm (2)
.SH AUTHOR
David van Moolenbroek <dcvmoole@cs.vu.nl>

View file

@ -16,7 +16,7 @@ CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$i
CFLAGS = $(CPROFILE) $(CPPFLAGS)
LDFLAGS = -i
OBJ = main.o forkexit.o break.o exec.o time.o timers.o \
OBJ = main.o forkexit.o break.o exec.o time.o timers.o alarm.o \
signal.o utility.o table.o trace.o getset.o misc.o \
profile.o dma.o

278
servers/pm/alarm.c Normal file
View file

@ -0,0 +1,278 @@
/* This file deals with the alarm clock related system calls, eventually
* passing off the work to the functions in timers.c and check_sig() in
* signal.c to pass an alarm signal to a process.
*
* The entry points into this file are:
* do_itimer: perform the ITIMER system call
* do_alarm: perform the ALARM system call
* set_alarm: tell the timer interface to start or stop a process timer
*/
#include "pm.h"
#include <signal.h>
#include <sys/time.h>
#include <string.h>
#include <minix/com.h>
#include "mproc.h"
#include "param.h"
#define US 1000000 /* shortcut for microseconds per second */
FORWARD _PROTOTYPE( clock_t ticks_from_timeval, (struct timeval *tv) );
FORWARD _PROTOTYPE( void timeval_from_ticks, (struct timeval *tv,
clock_t ticks) );
FORWARD _PROTOTYPE( int is_sane_timeval, (struct timeval *tv) );
FORWARD _PROTOTYPE( void get_realtimer, (struct mproc *mp,
struct itimerval *value) );
FORWARD _PROTOTYPE( void set_realtimer, (struct mproc *mp,
struct itimerval *value) );
FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp) );
/*===========================================================================*
* ticks_from_timeval *
*===========================================================================*/
PRIVATE clock_t ticks_from_timeval(tv)
struct timeval *tv;
{
clock_t ticks;
/* Large delays cause a lot of problems. First, the alarm system call
* takes an unsigned seconds count and the library has cast it to an int.
* That probably works, but on return the library will convert "negative"
* unsigneds to errors. Presumably no one checks for these errors, so
* force this call through. Second, If unsigned and long have the same
* size, converting from seconds to ticks can easily overflow. Finally,
* the kernel has similar overflow bugs adding ticks.
*
* Fixing this requires a lot of ugly casts to fit the wrong interface
* types and to avoid overflow traps. ALRM_EXP_TIME has the right type
* (clock_t) although it is declared as long. How can variables like
* this be declared properly without combinatorial explosion of message
* types?
*/
/* In any case, the following conversion must always round up. */
ticks = (clock_t) (system_hz * (unsigned long) tv->tv_sec);
if ( (unsigned long) ticks / system_hz != (unsigned long) tv->tv_sec) {
ticks = LONG_MAX;
} else {
ticks += (clock_t)
((system_hz * (unsigned long) tv->tv_usec + (US-1)) / US);
}
if (ticks < 0) ticks = LONG_MAX;
return(ticks);
}
/*===========================================================================*
* timeval_from_ticks *
*===========================================================================*/
PRIVATE void timeval_from_ticks(tv, ticks)
struct timeval *tv;
clock_t ticks;
{
tv->tv_sec = (long) (ticks / system_hz);
tv->tv_usec = (long) ((ticks % system_hz) * US / system_hz);
}
/*===========================================================================*
* is_sane_timeval *
*===========================================================================*/
PRIVATE int is_sane_timeval(tv)
struct timeval *tv;
{
/* This imposes a reasonable time value range for setitimer. */
return (tv->tv_sec >= 0 && tv->tv_sec <= MAX_SECS &&
tv->tv_usec >= 0 && tv->tv_usec < US);
}
/*===========================================================================*
* do_itimer *
*===========================================================================*/
PUBLIC int do_itimer()
{
struct itimerval ovalue, value; /* old and new interval timers */
int setval, getval; /* set and/or retrieve the values? */
int r;
/* Make sure 'which' is one of the defined timers. */
if (m_in.which_timer < ITIMER_REAL || m_in.which_timer > ITIMER_PROF)
return(EINVAL);
/* Determine whether to set and/or return the given timer value, based on
* which of the new_val and old_val parameters are nonzero. At least one of
* them must be nonzero.
*/
setval = (m_in.new_val != NULL);
getval = (m_in.old_val != NULL);
if (!setval && !getval) return(EINVAL);
/* If we're setting a new value, copy the new timer from user space.
* Also, make sure its fields have sane values.
*/
if (setval) {
r = sys_datacopy(who_e, (vir_bytes) m_in.new_val,
PM_PROC_NR, (vir_bytes) &value, (phys_bytes) sizeof(value));
if (r != OK) return(r);
if (!is_sane_timeval(&value.it_value) ||
!is_sane_timeval(&value.it_interval))
return(EINVAL);
}
switch (m_in.which_timer) {
case ITIMER_REAL :
if (getval) get_realtimer(mp, &ovalue);
if (setval) set_realtimer(mp, &value);
r = OK;
break;
case ITIMER_VIRTUAL :
case ITIMER_PROF :
/* Not implemented. */
r = ENOSYS;
break;
}
/* If requested, copy the old interval timer to user space. */
if (r == OK && getval) {
r = sys_datacopy(PM_PROC_NR, (vir_bytes) &ovalue,
who_e, (vir_bytes) m_in.old_val, (phys_bytes) sizeof(ovalue));
}
return(r);
}
/*===========================================================================*
* do_alarm *
*===========================================================================*/
PUBLIC int do_alarm()
{
struct itimerval value, ovalue;
int remaining; /* previous time left in seconds */
/* retrieve the old timer value, in seconds (rounded up) */
get_realtimer(mp, &ovalue);
remaining = ovalue.it_value.tv_sec;
if (ovalue.it_value.tv_usec > 0) remaining++;
/* set the new timer value */
memset(&value, 0, sizeof(value));
value.it_value.tv_sec = m_in.seconds;
set_realtimer(mp, &value);
/* and return the old timer value */
return(remaining);
}
/*===========================================================================*
* get_realtimer *
*===========================================================================*/
PRIVATE void get_realtimer(rmp, value)
struct mproc *rmp;
struct itimerval *value;
{
clock_t exptime; /* time at which alarm will expire */
clock_t uptime; /* current system time */
clock_t remaining; /* time left on alarm */
int s;
/* First determine remaining time, in ticks, of previous alarm, if set. */
if (rmp->mp_flags & ALARM_ON) {
if ( (s = getuptime(&uptime)) != OK)
panic(__FILE__, "get_realtimer couldn't get uptime", s);
exptime = *tmr_exp_time(&rmp->mp_timer);
remaining = exptime - uptime;
/* If the alarm expired already, we should take into account the
* interval. Return zero only if the interval is zero as well.
*/
if (remaining <= 0) remaining = rmp->mp_interval;
} else {
remaining = 0;
}
/* Convert the result to a timeval structure. */
timeval_from_ticks(&value->it_value, remaining);
/* Similarly convert and store the interval of the timer. */
timeval_from_ticks(&value->it_interval, rmp->mp_interval);
}
/*===========================================================================*
* set_realtimer *
*===========================================================================*/
PRIVATE void set_realtimer(rmp, value)
struct mproc *rmp;
struct itimerval *value;
{
clock_t ticks; /* New amount of ticks to the next alarm. */
clock_t interval; /* New amount of ticks for the alarm's interval. */
/* Convert the timeval structures in the 'value' structure to ticks. */
ticks = ticks_from_timeval(&value->it_value);
interval = ticks_from_timeval(&value->it_interval);
/* If no timer is set, the interval must be zero. */
if (ticks <= 0) interval = 0;
/* Apply these values. */
set_alarm(rmp, ticks);
rmp->mp_interval = interval;
}
/*===========================================================================*
* set_alarm *
*===========================================================================*/
PUBLIC void set_alarm(rmp, ticks)
struct mproc *rmp; /* process that wants the alarm */
clock_t ticks; /* how many ticks delay before the signal */
{
if (ticks > 0) {
pm_set_timer(&rmp->mp_timer, ticks, cause_sigalrm, rmp->mp_endpoint);
rmp->mp_flags |= ALARM_ON;
} else if (rmp->mp_flags & ALARM_ON) {
pm_cancel_timer(&rmp->mp_timer);
rmp->mp_flags &= ~ALARM_ON;
}
}
/*===========================================================================*
* cause_sigalrm *
*===========================================================================*/
PRIVATE void cause_sigalrm(tp)
struct timer *tp;
{
int proc_nr_n;
register struct mproc *rmp;
/* get process from timer */
if(pm_isokendpt(tmr_arg(tp)->ta_int, &proc_nr_n) != OK) {
printf("PM: ignoring timer for invalid endpoint %d\n",
tmr_arg(tp)->ta_int);
return;
}
rmp = &mproc[proc_nr_n];
if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) return;
if ((rmp->mp_flags & ALARM_ON) == 0) return;
/* If an interval is set, set a new timer; otherwise clear the ALARM_ON flag.
* The set_alarm call will be calling pm_set_timer from within this callback
* from the pm_expire_timers function. This is safe, but we must not use the
* "tp" structure below this point anymore. */
if (rmp->mp_interval > 0)
set_alarm(rmp, rmp->mp_interval);
else rmp->mp_flags &= ~ALARM_ON;
check_sig(rmp->mp_pid, SIGALRM);
}

View file

@ -10,3 +10,5 @@
#define DUMPED 0200 /* bit set in status when core dumped */
#define MAX_SECS (((1<<(sizeof(clock_t)*8-1))-1)/system_hz)
/* max.secs for setitimer() ((2^31-1)/HZ) */

View file

@ -86,6 +86,7 @@ PUBLIC int do_fork()
rmc->mp_exitstatus = 0;
rmc->mp_sigstatus = 0;
rmc->mp_endpoint = child_ep; /* passed back by VM */
rmc->mp_interval = 0; /* reset interval timer */
/* Find a free pid for the child and put it in the table. */
new_pid = get_free_pid();
@ -222,7 +223,7 @@ int dump_core; /* flag indicating whether to dump core */
procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
/* If the exited process has a timer pending, kill it. */
if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr_e, (unsigned) 0);
if (rmp->mp_flags & ALARM_ON) set_alarm(rmp, (clock_t) 0);
/* Do accounting: fetch usage times and accumulate at parent. */
if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL)) != OK)

View file

@ -38,7 +38,8 @@ EXTERN struct mproc {
struct sigmsg mp_sigmsg; /* Save the details of the signal until the
* PM_UNPAUSE request is delivered.
*/
struct timer mp_timer; /* watchdog timer for alarm(2) */
struct timer mp_timer; /* watchdog timer for alarm(2), setitimer(2) */
clock_t mp_interval; /* repetition interval for setitimer(2) */
unsigned mp_flags; /* flag bits */
vir_bytes mp_procargs; /* ptr to proc's initial stack arguments */

View file

@ -9,6 +9,9 @@
#define endpt m1_i1
#define pendpt m1_i2
#define seconds m1_i1
#define which_timer m1_i1
#define new_val m1_p1
#define old_val m1_p2
#define sig m6_i1
#define stack_bytes m1_i2
#define stack_ptr m1_p2

View file

@ -7,6 +7,11 @@ struct memory;
#include <timers.h>
/* alarm.c */
_PROTOTYPE( int do_alarm, (void) );
_PROTOTYPE( int do_itimer, (void) );
_PROTOTYPE( void set_alarm, (struct mproc *rmp, clock_t ticks) );
/* break.c */
_PROTOTYPE( int do_brk, (void) );
@ -73,11 +78,9 @@ _PROTOTYPE( int do_sprofile, (void) );
_PROTOTYPE( int do_cprofile, (void) );
/* signal.c */
_PROTOTYPE( int do_alarm, (void) );
_PROTOTYPE( int do_kill, (void) );
_PROTOTYPE( int ksig_pending, (void) );
_PROTOTYPE( int do_pause, (void) );
_PROTOTYPE( int set_alarm, (int proc_nr, int sec) );
_PROTOTYPE( int check_sig, (pid_t proc_id, int signo) );
_PROTOTYPE( void sig_proc, (struct mproc *rmp, int sig_nr) );
_PROTOTYPE( int do_sigaction, (void) );

View file

@ -11,8 +11,6 @@
* do_sigreturn: perform the SIGRETURN system call
* do_sigsuspend: perform the SIGSUSPEND system call
* do_kill: perform the KILL system call
* do_alarm: perform the ALARM system call by calling set_alarm()
* set_alarm: tell the clock task to start or stop a timer
* do_pause: perform the PAUSE system call
* ksig_pending: the kernel notified about pending signals
* sig_proc: interrupt or terminate a signaled process
@ -36,7 +34,6 @@
FORWARD _PROTOTYPE( void unpause, (int pro, int for_trace) );
FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map) );
FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp) );
/*===========================================================================*
* do_sigaction *
@ -290,101 +287,6 @@ sigset_t sig_map;
}
}
/*===========================================================================*
* do_alarm *
*===========================================================================*/
PUBLIC int do_alarm()
{
/* Perform the alarm(seconds) system call. */
return(set_alarm(who_e, m_in.seconds));
}
/*===========================================================================*
* set_alarm *
*===========================================================================*/
PUBLIC int set_alarm(proc_nr_e, sec)
int proc_nr_e; /* process that wants the alarm */
int sec; /* how many seconds delay before the signal */
{
/* This routine is used by do_alarm() to set the alarm timer. It is also used
* to turn the timer off when a process exits with the timer still on.
*/
clock_t ticks; /* number of ticks for alarm */
clock_t exptime; /* needed for remaining time on previous alarm */
clock_t uptime; /* current system time */
int remaining; /* previous time left in seconds */
int s;
int proc_nr_n;
if(pm_isokendpt(proc_nr_e, &proc_nr_n) != OK)
return EINVAL;
/* First determine remaining time of previous alarm, if set. */
if (mproc[proc_nr_n].mp_flags & ALARM_ON) {
if ( (s=getuptime(&uptime)) != OK)
panic(__FILE__,"set_alarm couldn't get uptime", s);
exptime = *tmr_exp_time(&mproc[proc_nr_n].mp_timer);
remaining = (int) ((exptime - uptime + (system_hz-1))/system_hz);
if (remaining < 0) remaining = 0;
} else {
remaining = 0;
}
/* Tell the clock task to provide a signal message when the time comes.
*
* Large delays cause a lot of problems. First, the alarm system call
* takes an unsigned seconds count and the library has cast it to an int.
* That probably works, but on return the library will convert "negative"
* unsigneds to errors. Presumably no one checks for these errors, so
* force this call through. Second, If unsigned and long have the same
* size, converting from seconds to ticks can easily overflow. Finally,
* the kernel has similar overflow bugs adding ticks.
*
* Fixing this requires a lot of ugly casts to fit the wrong interface
* types and to avoid overflow traps. ALRM_EXP_TIME has the right type
* (clock_t) although it is declared as long. How can variables like
* this be declared properly without combinatorial explosion of message
* types?
*/
ticks = (clock_t) (system_hz * (unsigned long) (unsigned) sec);
if ( (unsigned long) ticks / system_hz != (unsigned) sec)
ticks = LONG_MAX; /* eternity (really TMR_NEVER) */
if (ticks != 0) {
pm_set_timer(&mproc[proc_nr_n].mp_timer, ticks,
cause_sigalrm, proc_nr_e);
mproc[proc_nr_n].mp_flags |= ALARM_ON;
} else if (mproc[proc_nr_n].mp_flags & ALARM_ON) {
pm_cancel_timer(&mproc[proc_nr_n].mp_timer);
mproc[proc_nr_n].mp_flags &= ~ALARM_ON;
}
return(remaining);
}
/*===========================================================================*
* cause_sigalrm *
*===========================================================================*/
PRIVATE void cause_sigalrm(tp)
struct timer *tp;
{
int proc_nr_n;
register struct mproc *rmp;
/* get process from timer */
if(pm_isokendpt(tmr_arg(tp)->ta_int, &proc_nr_n) != OK) {
printf("PM: ignoring timer for invalid endpoint %d\n",
tmr_arg(tp)->ta_int);
return;
}
rmp = &mproc[proc_nr_n];
if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) return;
if ((rmp->mp_flags & ALARM_ON) == 0) return;
rmp->mp_flags &= ~ALARM_ON;
check_sig(rmp->mp_pid, SIGALRM);
}
/*===========================================================================*
* do_pause *
*===========================================================================*/

View file

@ -78,8 +78,7 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = {
no_sys, /* 61 = chroot */
do_getset, /* 62 = setsid */
do_getset, /* 63 = getpgrp */
no_sys, /* 64 = unused */
do_itimer, /* 64 = itimer */
no_sys, /* 65 = unused */
no_sys, /* 66 = unused */
no_sys, /* 67 = unused */

View file

@ -20,6 +20,7 @@
#include <minix/com.h>
PRIVATE timer_t *pm_timers = NULL;
PRIVATE int pm_expiring = 0;
/*===========================================================================*
* pm_set_timer *
@ -37,7 +38,7 @@ PUBLIC void pm_set_timer(timer_t *tp, int ticks, tmr_func_t watchdog, int arg)
prev_time = tmrs_settimer(&pm_timers,tp,now+ticks,watchdog,&next_time);
/* Reschedule our synchronous alarm if necessary. */
if (! prev_time || prev_time > next_time) {
if (pm_expiring == 0 && (! prev_time || prev_time > next_time)) {
if (sys_setalarm(next_time, 1) != OK)
panic(__FILE__, "PM set timer couldn't set alarm.", NO_NUM);
}
@ -52,8 +53,15 @@ PUBLIC void pm_expire_timers(clock_t now)
{
clock_t next_time;
/* Check for expired timers and possibly reschedule an alarm. */
/* Check for expired timers. Use a global variable to indicate that
* watchdog functions are called, so that sys_setalarm() isn't called
* more often than necessary when pm_set_timer or pm_cancel_timer are
* called from these watchdog functions. */
pm_expiring = 1;
tmrs_exptimers(&pm_timers, now, &next_time);
pm_expiring = 0;
/* Reschedule an alarm if necessary. */
if (next_time > 0) {
if (sys_setalarm(next_time, 1) != OK)
panic(__FILE__, "PM expire timer couldn't set alarm.", NO_NUM);
@ -72,7 +80,7 @@ PUBLIC void pm_cancel_timer(timer_t *tp)
* the next timer, or cancel the alarm altogether if the last timer has
* been cancelled (next_time will be 0 then).
*/
if (prev_time < next_time || ! next_time) {
if (pm_expiring == 0 && (prev_time < next_time || ! next_time)) {
if (sys_setalarm(next_time, 1) != OK)
panic(__FILE__, "PM expire timer couldn't set alarm.", NO_NUM);
}

View file

@ -80,8 +80,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
do_chroot, /* 61 = chroot */
no_sys, /* 62 = (setsid) */
no_sys, /* 63 = (getpgrp) */
no_sys, /* 64 = unused */
no_sys, /* 64 = (itimer) */
no_sys, /* 65 = unused */
no_sys, /* 66 = unused */
no_sys, /* 67 = unused */
@ -95,7 +94,6 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
no_sys, /* 75 = (sigreturn) */
no_sys, /* 76 = (reboot) */
do_svrctl, /* 77 = svrctl */
no_sys, /* 78 = (sysuname) */
do_getsysinfo, /* 79 = getsysinfo */
do_getdents, /* 80 = getdents */