Support for setitimer(ITIMER_REAL).
This commit is contained in:
parent
062bb2c1e8
commit
d82e260a90
20 changed files with 449 additions and 111 deletions
|
@ -53,6 +53,7 @@
|
|||
#define CHROOT 61
|
||||
#define SETSID 62
|
||||
#define GETPGRP 63
|
||||
#define ITIMER 64
|
||||
|
||||
/* Posix signal handling. */
|
||||
#define SIGACTION 71
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
18
lib/posix/_getitimer.c
Normal 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
24
lib/posix/_setitimer.c
Normal 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);
|
||||
}
|
|
@ -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
7
lib/syscall/getitimer.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.extern __getitimer
|
||||
.define _getitimer
|
||||
.align 2
|
||||
|
||||
_getitimer:
|
||||
jmp __getitimer
|
7
lib/syscall/setitimer.s
Normal file
7
lib/syscall/setitimer.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.extern __setitimer
|
||||
.define _setitimer
|
||||
.align 2
|
||||
|
||||
_setitimer:
|
||||
jmp __setitimer
|
67
man/man2/getitimer.2
Normal file
67
man/man2/getitimer.2
Normal 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>
|
|
@ -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
278
servers/pm/alarm.c
Normal 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);
|
||||
}
|
|
@ -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) */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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 *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue