Kernel: export clock information on kernel page

Please note that this information is for use by system services only!
The clock facility is not ready to be used directly by userland, and
thus, this kernel page extension is NOT part of the userland ABI.

For service programmers' convenience, change the prototype of the
getticks(3) to return the uptime clock value directly, since the call
can no longer fail.

Correct the sys_times(2) reply message to use the right field type
for the boot time.

Restructure the kernel internals a bit so as to have all the clock
stuff closer together.

Change-Id: Ifc050b7bd253aecbe46e3bd7d7cc75bd86e45555
This commit is contained in:
David van Moolenbroek 2015-09-21 13:07:55 +00:00
parent 594df55e53
commit d91f738bd8
37 changed files with 175 additions and 183 deletions

View file

@ -133,7 +133,7 @@ static int el1_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
clock_t now;
if (dep->de_flags & DEF_XMIT_BUSY) {
getticks(&now);
now = getticks();
if ((now - dep->de_xmit_start) > 4) {
/* Transmitter timed out */
DEBUG(printf("3c501: transmitter timed out ... \n"));
@ -171,7 +171,7 @@ static int el1_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - size));
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT); /* There it goes... */
getticks(&dep->de_xmit_start);
dep->de_xmit_start = getticks();
return OK;
}

View file

@ -194,7 +194,7 @@ static int el3_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
short int TxStatus;
size_t padding;
getticks(&now);
now = getticks();
if ((dep->de_flags & DEF_XMIT_BUSY) &&
(now - dep->de_xmit_start) > 4) {
@ -217,7 +217,7 @@ static int el3_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
padding = size;
while ((padding++ % sizeof(long)) != 0) outb(dep->de_data_port, 0x00);
getticks(&dep->de_xmit_start);
dep->de_xmit_start = getticks();
dep->de_flags |= DEF_XMIT_BUSY;
if (inw_el3(dep, REG_TxFree) > ETH_MAX_PACK_SIZE) {
/* Tx has enough room for a packet of maximum size */

View file

@ -50,8 +50,6 @@ static struct optset optset_table[] = {
*===========================================================================*/
static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
{
clock_t uptime;
int r;
/* Parse the given parameters. */
if (env_argc > 1)
@ -74,12 +72,10 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
/* Initialize resources. */
fbd_buf = alloc_contig(BUF_SIZE, 0, NULL);
assert(fbd_buf != NULL);
if (fbd_buf == NULL)
panic("unable to allocate buffer");
if ((r = getticks(&uptime)) != OK)
panic("getuptime failed (%d)\n", r);
srand48(uptime);
srand48(getticks());
/* Announce we are up! */
blockdriver_announce(type);

View file

@ -60,9 +60,7 @@ clock_t flt_alarm(clock_t dt)
} else {
if(next_alarm)
panic("overwriting alarm: %d", r);
if ((r = getticks(&next_alarm)) != OK)
panic("getuptime failed: %d", r);
next_alarm += dt;
next_alarm = getticks() + dt;
}
return next_alarm;

View file

@ -74,12 +74,9 @@ root_loadavg(void)
static void
root_uptime(void)
{
clock_t ticks;
ldiv_t division;
if (getticks(&ticks) != OK)
return;
division = ldiv(100L * ticks / sys_hz(), 100L);
division = ldiv(100L * getticks() / sys_hz(), 100L);
buf_printf("%ld.%0.2ld\n", division.quot, division.rem);
}

View file

@ -426,14 +426,12 @@ lookup_hook(struct inode * parent, char * name, cbdata_t __unused cbdata)
{
static clock_t last_update = 0;
clock_t now;
int r;
/*
* Update lazily for lookups, as this gets too expensive otherwise.
* Alternative: pull in only PM's table?
*/
if ((r = getticks(&now)) != OK)
panic("unable to get uptime: %d", r);
now = getticks();
if (last_update != now) {
update_tables();

View file

@ -305,11 +305,11 @@ _ASSERT_MSG_SIZE(mess_krn_lsys_sys_irqctl);
typedef struct {
clock_t real_ticks;
clock_t boot_ticks;
clock_t boot_time;
clock_t user_time;
clock_t system_time;
time_t boot_time;
uint8_t padding[36];
uint8_t padding[32];
} mess_krn_lsys_sys_times;
_ASSERT_MSG_SIZE(mess_krn_lsys_sys_times);

View file

@ -55,7 +55,7 @@ __dead void panic(const char *fmt, ...)
void panic_hook(void);
void __panic_hook(void);
int getuptime(clock_t *ticks, clock_t *realtime, time_t *boottime);
int getticks(clock_t *ticks);
clock_t getticks(void);
int tickdelay(clock_t ticks);
int tsc_calibrate(void);
u32_t sys_hz(void);

View file

@ -2,6 +2,7 @@
#define _TYPE_H
#include <sys/types.h>
#include <sys/endian.h>
#include <machine/multiboot.h>
@ -91,6 +92,24 @@ struct loadinfo {
clock_t last_clock;
};
struct kclockinfo {
time_t boottime; /* number of seconds since UNIX epoch */
#if BYTE_ORDER == LITTLE_ENDIAN
clock_t uptime; /* number of clock ticks since system boot */
uint32_t _rsvd1; /* reserved for 64-bit uptime */
clock_t realtime; /* real time in clock ticks since boot */
uint32_t _rsvd2; /* reserved for 64-bit real time */
#elif BYTE_ORDER == BIG_ENDIAN
uint32_t _rsvd1; /* reserved for 64-bit uptime */
clock_t uptime; /* number of clock ticks since system boot */
uint32_t _rsvd2; /* reserved for 64-bit real time */
clock_t realtime; /* real time in clock ticks since boot */
#else
#error "unknown endianness"
#endif
uint32_t hz; /* clock frequency in ticks per second */
};
struct machine {
unsigned processors_count; /* how many cpus are available */
unsigned bsp_id; /* id of the bootstrap cpu */
@ -174,15 +193,16 @@ struct minix_kerninfo {
u32_t kerninfo_magic;
u32_t minix_feature_flags; /* features in minix kernel */
u32_t ki_flags; /* what is present in this struct */
u32_t minix_frclock_tcrr;
u32_t minix_frclock_tcrr; /* NOT userland ABI */
u32_t flags_unused3;
u32_t flags_unused4;
struct kinfo *kinfo;
struct machine *machine;
struct kmessages *kmessages;
struct loadinfo *loadinfo;
struct machine *machine; /* NOT userland ABI */
struct kmessages *kmessages; /* NOT userland ABI */
struct loadinfo *loadinfo; /* NOT userland ABI */
struct minix_ipcvecs *minix_ipcvecs;
u64_t minix_arm_frclock_hz; /* minix_frclock_tcrr frequency */
u64_t minix_arm_frclock_hz; /* minix_frclock_tcrr frequency !ABI */
volatile struct kclockinfo *kclockinfo; /* NOT userland ABI */
} __packed;
#define MINIX_KIF_IPCVECS (1L << 0)

View file

@ -714,6 +714,7 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
ASSIGN(machine);
ASSIGN(kmessages);
ASSIGN(loadinfo);
ASSIGN(kclockinfo);
/* adjust the pointers of the functions and the struct
* itself to the user-accessible mapping

View file

@ -879,6 +879,7 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
ASSIGN(machine);
ASSIGN(kmessages);
ASSIGN(loadinfo);
ASSIGN(kclockinfo);
/* select the right set of IPC routines to map into processes */
if(minix_feature_flags & MKF_I386_INTEL_SYSENTER) {

View file

@ -1,9 +1,8 @@
/* This file contains the clock task, which handles time related functions.
* Important events that are handled by the CLOCK include setting and
* monitoring alarm timers and deciding when to (re)schedule processes.
* The CLOCK offers a direct interface to kernel processes. System services
* can access its services through system calls, such as sys_setalarm(). The
* CLOCK task thus is hidden from the outside world.
/* This file contains the architecture-independent clock functionality, which
* handles time related functions. Important events that are handled here
* include setting and monitoring alarm timers and deciding when to
* (re)schedule processes. System services can access its services through
* system calls, such as sys_setalarm().
*
* Changes:
* Aug 18, 2006 removed direct hardware access etc, MinixPPC (Ingmar Alting)
@ -11,29 +10,12 @@
* Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
* Sep 24, 2004 redesigned alarm timers (Jorrit N. Herder)
*
* Clock task is notified by the clock's interrupt handler when a timer
* has expired.
*
* In addition to the main clock_task() entry point, which starts the main
* loop, there are several other minor entry points:
* clock_stop: called just before MINIX shutdown
* get_realtime: get wall time since boot in clock ticks
* set_realtime: set wall time since boot in clock ticks
* set_adjtime_delta: set the number of ticks to adjust realtime
* get_monotonic: get monotonic time since boot in clock ticks
* set_kernel_timer: set a watchdog timer (+)
* reset_kernel_timer: reset a watchdog timer (+)
* read_clock: read the counter of channel 0 of the 8253A timer
*
* (+) The CLOCK task keeps tracks of watchdog timers for the entire kernel.
* It is crucial that watchdog functions not block, or the CLOCK task may
* be blocked. Do not send() a message when the receiver is not expecting it.
* Instead, notify(), which always returns, should be used.
*/
#include "kernel/kernel.h"
#include <minix/endpoint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "clock.h"
@ -56,19 +38,34 @@ static void load_update(void);
static minix_timer_t *clock_timers; /* queue of CLOCK timers */
static clock_t next_timeout; /* monotonic time that next timer expires */
/* The time is incremented by the interrupt handler on each clock tick.
*/
static clock_t monotonic = 0;
/* Reflects the wall time and may be slowed/sped up by using adjclock()
*/
static clock_t realtime = 0;
/* Number of ticks to adjust realtime by. A negative value implies slowing
* down realtime, a positive value implies speeding it up.
*/
static int32_t adjtime_delta = 0;
/*
* Initialize the clock variables.
*/
void
init_clock(void)
{
char *value;
int i;
/* Initialize clock information structure. */
memset(&kclockinfo, 0, sizeof(kclockinfo));
/* Get clock tick frequency. */
value = env_get("hz");
if (value != NULL)
kclockinfo.hz = atoi(value);
if (value == NULL || kclockinfo.hz < 2 || kclockinfo.hz > 50000)
kclockinfo.hz = DEFAULT_HZ;
/* Load average data initialization. */
memset(&kloadinfo, 0, sizeof(kloadinfo));
}
/*
* The boot processor's timer interrupt handler. In addition to non-boot cpus
* it keeps real time and notifies the clock task if need be.
@ -95,17 +92,17 @@ int timer_int_handler(void)
#endif
if (cpu_is_bsp(cpuid)) {
monotonic++;
kclockinfo.uptime++;
/* if adjtime_delta has ticks remaining, apply one to realtime.
* limit changes to every other interrupt.
*/
if (adjtime_delta != 0 && monotonic & 0x1) {
if (adjtime_delta != 0 && kclockinfo.uptime & 0x1) {
/* go forward or stay behind */
realtime += (adjtime_delta > 0) ? 2 : 0;
kclockinfo.realtime += (adjtime_delta > 0) ? 2 : 0;
adjtime_delta += (adjtime_delta > 0) ? -1 : +1;
} else {
realtime++;
kclockinfo.realtime++;
}
}
@ -158,8 +155,8 @@ int timer_int_handler(void)
if (cpu_is_bsp(cpuid)) {
/* if a timer expired, notify the clock task */
if ((next_timeout <= monotonic)) {
tmrs_exptimers(&clock_timers, monotonic, NULL);
if ((next_timeout <= kclockinfo.uptime)) {
tmrs_exptimers(&clock_timers, kclockinfo.uptime, NULL);
next_timeout = (clock_timers == NULL) ?
TMR_NEVER : clock_timers->tmr_exp_time;
}
@ -182,7 +179,7 @@ int timer_int_handler(void)
clock_t get_realtime(void)
{
/* Get and return the current wall time in ticks since boot. */
return(realtime);
return(kclockinfo.realtime);
}
/*===========================================================================*
@ -190,7 +187,7 @@ clock_t get_realtime(void)
*===========================================================================*/
void set_realtime(clock_t newrealtime)
{
realtime = newrealtime;
kclockinfo.realtime = newrealtime;
}
/*===========================================================================*
@ -207,7 +204,24 @@ void set_adjtime_delta(int32_t ticks)
clock_t get_monotonic(void)
{
/* Get and return the number of ticks since boot. */
return(monotonic);
return(kclockinfo.uptime);
}
/*===========================================================================*
* set_boottime *
*===========================================================================*/
void set_boottime(time_t newboottime)
{
kclockinfo.boottime = newboottime;
}
/*===========================================================================*
* get_boottime *
*===========================================================================*/
time_t get_boottime(void)
{
/* Get and return the number of seconds since the UNIX epoch. */
return(kclockinfo.boottime);
}
/*===========================================================================*
@ -256,7 +270,8 @@ static void load_update(void)
* be made of the load average over variable periods, in the
* user library (see getloadavg(3)).
*/
slot = (monotonic / system_hz / _LOAD_UNIT_SECS) % _LOAD_HISTORY;
slot = (kclockinfo.uptime / system_hz / _LOAD_UNIT_SECS) %
_LOAD_HISTORY;
if(slot != kloadinfo.proc_last_slot) {
kloadinfo.proc_load_history[slot] = 0;
kloadinfo.proc_last_slot = slot;
@ -273,7 +288,7 @@ static void load_update(void)
kloadinfo.proc_load_history[slot] += enqueued;
/* Up-to-dateness. */
kloadinfo.last_clock = monotonic;
kloadinfo.last_clock = kclockinfo.uptime;
}
int boot_cpu_init_timer(unsigned freq)

View file

@ -23,6 +23,7 @@ extern struct kinfo kinfo; /* kernel information for users */
extern struct machine machine; /* machine information for users */
extern struct kmessages kmessages; /* diagnostic messages in kernel */
extern struct loadinfo loadinfo; /* status of load average */
extern struct kclockinfo kclockinfo; /* clock information */
extern struct minix_kerninfo minix_kerninfo;
EXTERN struct k_randomness krandom; /* gather kernel random information */
@ -32,6 +33,8 @@ EXTERN vir_bytes minix_kerninfo_user;
#define kmess kmessages
#define kloadinfo loadinfo
#define system_hz (kclockinfo.hz) /* HZ value (alias) */
/* Process scheduling information and the kernel reentry count. */
EXTERN struct proc *vmrequest; /* first process on vmrequest queue */
EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */
@ -43,10 +46,8 @@ EXTERN struct proc *kbill_ipc; /* process that invoked ipc */
EXTERN irq_hook_t irq_hooks[NR_IRQ_HOOKS]; /* hooks for general use */
EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */
EXTERN int irq_use; /* map of all in-use irq's */
EXTERN u32_t system_hz; /* HZ value */
/* Miscellaneous. */
EXTERN time_t boottime;
EXTERN int verboseboot; /* verbose boot, init'ed in cstart */
#if DEBUG_TRACE

View file

@ -410,7 +410,6 @@ void cstart()
* determined with help of the environment strings passed by MINIX' loader.
*/
register char *value; /* value in key=value pair */
int h;
/* low-level initialization */
prot_init();
@ -419,12 +418,8 @@ void cstart()
if ((value = env_get(VERBOSEBOOTVARNAME)))
verboseboot = atoi(value);
/* Get clock tick frequency. */
value = env_get("hz");
if(value)
system_hz = atoi(value);
if(!value || system_hz < 2 || system_hz > 50000) /* sanity check */
system_hz = DEFAULT_HZ;
/* Initialize clock variables. */
init_clock();
/* Get memory parameters. */
value = env_get("ac_layout");
@ -441,11 +436,6 @@ void cstart()
strlcpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
strlcpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
/* Load average data initialization. */
kloadinfo.proc_last_slot = 0;
for(h = 0; h < _LOAD_HISTORY; h++)
kloadinfo.proc_load_history[h] = 0;
#ifdef USE_APIC
value = env_get("no_apic");
if(value)

View file

@ -16,10 +16,13 @@ struct proc;
struct ipc_filter_s;
/* clock.c */
void init_clock(void);
clock_t get_realtime(void);
void set_realtime(clock_t);
void set_adjtime_delta(int32_t);
clock_t get_monotonic(void);
void set_boottime(time_t);
time_t get_boottime(void);
void set_kernel_timer(minix_timer_t *tp, clock_t t, tmr_func_t f);
void reset_kernel_timer(minix_timer_t *tp);
void ser_dump_proc(void);

View file

@ -19,19 +19,23 @@ int do_settime(struct proc * caller, message * m_ptr)
{
clock_t newclock;
int32_t ticks;
time_t timediff, timediff_ticks;
time_t boottime, timediff, timediff_ticks;
if (m_ptr->m_lsys_krn_sys_settime.clock_id != CLOCK_REALTIME) /* only realtime can change */
/* only realtime can change */
if (m_ptr->m_lsys_krn_sys_settime.clock_id != CLOCK_REALTIME)
return EINVAL;
if (m_ptr->m_lsys_krn_sys_settime.now == 0) { /* user just wants to adjtime() */
/* user just wants to adjtime() */
if (m_ptr->m_lsys_krn_sys_settime.now == 0) {
/* convert delta value from seconds and nseconds to ticks */
ticks = (m_ptr->m_lsys_krn_sys_settime.sec * system_hz) +
(m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz));
(m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz));
set_adjtime_delta(ticks);
return(OK);
} /* else user wants to set the time */
boottime = get_boottime();
timediff = m_ptr->m_lsys_krn_sys_settime.sec - boottime;
timediff_ticks = timediff * system_hz;
@ -39,7 +43,7 @@ int do_settime(struct proc * caller, message * m_ptr)
if (m_ptr->m_lsys_krn_sys_settime.sec <= boottime ||
timediff_ticks < LONG_MIN/2 || timediff_ticks > LONG_MAX/2) {
/* boottime was likely wrong, try to correct it. */
boottime = m_ptr->m_lsys_krn_sys_settime.sec;
set_boottime(m_ptr->m_lsys_krn_sys_settime.sec);
set_realtime(1);
return(OK);
}

View file

@ -14,6 +14,6 @@
*===========================================================================*/
int do_stime(struct proc * caller, message * m_ptr)
{
boottime = m_ptr->m_lsys_krn_sys_stime.boot_time;
set_boottime(m_ptr->m_lsys_krn_sys_stime.boot_time);
return(OK);
}

View file

@ -39,7 +39,7 @@ int do_times(struct proc * caller, message * m_ptr)
}
m_ptr->m_krn_lsys_sys_times.boot_ticks = get_monotonic();
m_ptr->m_krn_lsys_sys_times.real_ticks = get_realtime();
m_ptr->m_krn_lsys_sys_times.boot_time = boottime;
m_ptr->m_krn_lsys_sys_times.boot_time = get_boottime();
return(OK);
}

View file

@ -8,4 +8,4 @@ struct kinfo kinfo __section(".usermapped"); /* kernel information for users */
struct machine machine __section(".usermapped"); /* machine information for users */
struct kmessages kmessages __section(".usermapped"); /* diagnostic messages in kernel */
struct loadinfo loadinfo __section(".usermapped"); /* status of load average */
struct kclockinfo kclockinfo __section(".usermapped"); /* clock information */

View file

@ -43,7 +43,6 @@ static ddekit_lock_t lock;
static void lock_timer(void);
static void unlock_timer(void);
static clock_t get_current_clock(void);
static void remove_timer(int id);
static int insert_timer(struct ddekit_timer_s *t);
static struct ddekit_timer_s * get_next( myclock_t exp );
@ -69,17 +68,6 @@ static void unlock_timer()
ddekit_lock_unlock(&lock);
}
/*****************************************************************************
* get_current_clock *
****************************************************************************/
static myclock_t get_current_clock()
{
/* returns the current clock tick */
myclock_t ret;
getticks(&ret);
return ret;
}
/*****************************************************************************
* remove_timer *
****************************************************************************/
@ -251,7 +239,7 @@ void ddekit_init_timers(void)
if (!first_time)
{
ddekit_lock_init(&lock);
jiffies = get_current_clock();
jiffies = getticks();
HZ = sys_hz();
pending_timer_ints = ddekit_sem_init(0);
th = ddekit_thread_create(ddekit_timer_thread, 0, "timer");
@ -277,7 +265,7 @@ ddekit_thread_t *ddekit_get_timer_thread(void)
****************************************************************************/
void _ddekit_timer_interrupt(void)
{
jiffies = get_current_clock();
jiffies = getticks();
DDEBUG_MSG_VERBOSE("now: %d", jiffies);
ddekit_sem_up(pending_timer_ints);
}

View file

@ -6,12 +6,7 @@
u32_t sys_jiffies(void)
{
clock_t ticks;
if (getticks(&ticks) == OK)
return ticks;
else
panic("getuptime() failed\n");
return getticks();
}
u32_t sys_now(void)

View file

@ -70,14 +70,14 @@ int spin_check(spin_t *s)
if (micro_delta >= TSC_SPIN) {
s->s_usecs -= micro_delta;
getticks(&s->s_base_uptime);
s->s_base_uptime = getticks();
s->s_state = STATE_UPTIME;
}
break;
case STATE_UPTIME:
getticks(&now);
now = getticks();
/* We assume that sys_hz() caches its return value. */
micro_delta = ((now - s->s_base_uptime) * 1000 / sys_hz()) *

View file

@ -72,14 +72,14 @@ int spin_check(spin_t *s)
if (micro_delta >= TSC_SPIN) {
s->s_usecs -= micro_delta;
getticks(&s->s_base_uptime);
s->s_base_uptime = getticks();
s->s_state = STATE_UPTIME;
}
break;
case STATE_UPTIME:
getticks(&now);
now = getticks();
/* We assume that sys_hz() caches its return value. */
micro_delta = ((now - s->s_base_uptime) * 1000 / sys_hz()) *

View file

@ -12,15 +12,17 @@
time_t
clock_time(struct timespec *tv)
{
struct minix_kerninfo *minix_kerninfo;
uint32_t system_hz;
clock_t uptime, realtime;
clock_t realtime;
time_t boottime, sec;
int r;
if ((r = getuptime(&uptime, &realtime, &boottime)) != OK)
panic("clock_time: getuptime failed: %d", r);
minix_kerninfo = get_minix_kerninfo();
system_hz = sys_hz(); /* sys_hz() caches its return value */
/* We assume atomic 32-bit field retrieval. TODO: 64-bit support. */
boottime = minix_kerninfo->kclockinfo->boottime;
realtime = minix_kerninfo->kclockinfo->realtime;
system_hz = minix_kerninfo->kclockinfo->hz;
sec = boottime + realtime / system_hz;

View file

@ -1,17 +1,13 @@
#include "sysutil.h"
/*===========================================================================*
* getuptime *
*===========================================================================*/
int getticks(ticks)
clock_t *ticks; /* monotonic time in ticks */
/*
* Return the number of clock ticks since system boot. Note that the value may
* wrap on overflow.
*/
clock_t
getticks(void)
{
message m;
int s;
m.m_type = SYS_TIMES; /* request time information */
m.m_lsys_krn_sys_times.endpt = NONE; /* ignore process times */
s = _kernel_call(SYS_TIMES, &m);
*ticks = m.m_krn_lsys_sys_times.boot_ticks;
return(s);
/* We assume atomic 32-bit field retrieval. TODO: 64-bit support. */
return get_minix_kerninfo()->kclockinfo->uptime;
}

View file

@ -1,21 +1,21 @@
#include "sysutil.h"
/*===========================================================================*
* getuptime *
*===========================================================================*/
int getuptime(ticks, realtime, boottime)
clock_t *ticks; /* monotonic time in ticks */
clock_t *realtime; /* wall time in ticks */
time_t *boottime;
/*
* Retrieve the system's uptime (number of clock ticks since system boot),
* real time (corrected number of clock ticks since system boot), and
* boot time (in number of seconds since the UNIX epoch).
*/
int
getuptime(clock_t * uptime, clock_t * realtime, time_t * boottime)
{
message m;
int s;
struct minix_kerninfo *minix_kerninfo;
m.m_type = SYS_TIMES; /* request time information */
m.m_lsys_krn_sys_times.endpt = NONE; /* ignore process times */
s = _kernel_call(SYS_TIMES, &m);
*ticks = m.m_krn_lsys_sys_times.boot_ticks;
*realtime = m.m_krn_lsys_sys_times.real_ticks;
*boottime = m.m_krn_lsys_sys_times.boot_time;
return(s);
minix_kerninfo = get_minix_kerninfo();
/* We assume atomic 32-bit field retrieval. TODO: 64-bit support. */
*uptime = minix_kerninfo->kclockinfo->uptime;
*realtime = minix_kerninfo->kclockinfo->realtime;
*boottime = minix_kerninfo->kclockinfo->boottime;
return OK;
}

View file

@ -302,9 +302,7 @@ void sef_cancel(void)
*===========================================================================*/
int sef_getrndseed(void)
{
clock_t uptime;
sys_times(SELF, NULL, NULL, &uptime, NULL);
return (int) uptime;
return (int)getticks();
}
/*===========================================================================*

View file

@ -31,15 +31,12 @@ void init_timer(minix_timer_t *tp)
*===========================================================================*/
void set_timer(minix_timer_t *tp, int ticks, tmr_func_t watchdog, int arg)
{
int r;
clock_t now, prev_time = 0, next_time;
if ((r = getticks(&now)) != OK)
panic("set_timer: couldn't get uptime");
clock_t prev_time = 0, next_time;
/* Set timer argument and add timer to the list. */
tmr_arg(tp)->ta_int = arg;
prev_time = tmrs_settimer(&timers, tp, now+ticks, watchdog, &next_time);
prev_time = tmrs_settimer(&timers, tp, getticks() + ticks, watchdog,
&next_time);
/* Reschedule our synchronous alarm if necessary. */
if (expiring == 0 && (! prev_time || prev_time > next_time)) {

View file

@ -35,9 +35,8 @@ time_t get_time()
{
if (!curr_time)
{
if (getticks(&curr_time) != OK)
ip_panic(("can't read clock"));
assert(curr_time >= prev_time);
curr_time = getticks();
assert(curr_time >= prev_time); /* XXX */
}
return curr_time;
}

View file

@ -81,7 +81,7 @@ void sigaction_dmp()
printf("Error obtaining table from PM. Perhaps recompile IS?\n");
return;
}
getticks(&uptime);
uptime = getticks();
printf("Process manager (PM) signal action dump\n");
printf("-process- -nr- --ignore- --catch- --block- -pending- -alarm---\n");

View file

@ -252,12 +252,10 @@ 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 = getticks(&uptime)) != OK)
panic("get_realtimer couldn't get uptime: %d", s);
uptime = getticks();
exptime = *tmr_exp_time(&rmp->mp_timer);
remaining = exptime - uptime;

View file

@ -329,7 +329,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
rp->r_next_rp = NULL; /* no next replica yet */
rp->r_uid = 0; /* root */
rp->r_check_tm = 0; /* not checked yet */
getticks(&rp->r_alive_tm); /* currently alive */
rp->r_alive_tm = getticks(); /* currently alive */
rp->r_stop_tm = 0; /* not exiting yet */
rp->r_asr_count = 0; /* no ASR updates yet */
rp->r_restarts = 0; /* no restarts so far */
@ -815,7 +815,7 @@ endpoint_t endpoint;
/* Mark the slot as no longer initializing. */
rp->r_flags &= ~RS_INITIALIZING;
rp->r_check_tm = 0;
getticks(&rp->r_alive_tm);
rp->r_alive_tm = getticks();
}
/*===========================================================================*

View file

@ -601,7 +601,7 @@ struct rproc *rp;
rpub->endpoint = child_proc_nr_e; /* set child endpoint */
rp->r_pid = child_pid; /* set child pid */
rp->r_check_tm = 0; /* not checked yet */
getticks(&rp->r_alive_tm); /* currently alive */
rp->r_alive_tm = getticks(); /* currently alive */
rp->r_stop_tm = 0; /* not exiting yet */
rp->r_backoff = 0; /* not to be restarted */
rproc_ptr[child_proc_nr_n] = rp; /* mapping for fast access */
@ -1014,7 +1014,7 @@ void stop_service(struct rproc *rp,int how)
rp->r_flags |= how; /* what to on exit? */
sys_kill(rpub->endpoint, signo); /* first try friendly */
getticks(&rp->r_stop_tm); /* record current time */
rp->r_stop_tm = getticks(); /* record current time */
}
/*===========================================================================*

View file

@ -508,7 +508,7 @@ int do_init_ready(message *m_ptr)
/* Mark the slot as no longer initializing. */
rp->r_flags &= ~RS_INITIALIZING;
rp->r_check_tm = 0;
getticks(&rp->r_alive_tm);
rp->r_alive_tm = getticks();
/* Reply and unblock the service before doing anything else. */
m.m_type = OK;
@ -842,7 +842,7 @@ int do_update(message *m_ptr)
/* Fill the new update descriptor and add it to the update chain. */
rpupd->prepare_state = prepare_state;
rpupd->state_endpoint = state_endpoint;
getticks(&rpupd->prepare_tm);
rpupd->prepare_tm = getticks();
rpupd->prepare_maxtime = prepare_maxtime;
rupdate_add_upd(rpupd);

View file

@ -194,7 +194,7 @@ void request_prepare_update_service_debug(char *file, int line,
if(state != SEF_LU_STATE_NULL) {
struct rprocupd *rpupd = &rp->r_upd;
getticks(&rpupd->prepare_tm);
rpupd->prepare_tm = getticks();
if(!UPD_IS_PREPARING_ONLY(rpupd)) {
assert(rp->r_new_rp);
rp->r_flags |= RS_UPDATING;
@ -965,7 +965,7 @@ void end_srv_update(struct rprocupd *rpupd, int result, int reply_flag)
exiting_rp = (result == OK ? old_rp : new_rp);
surviving_rp->r_flags &= ~RS_INITIALIZING;
surviving_rp->r_check_tm = 0;
getticks(&surviving_rp->r_alive_tm);
surviving_rp->r_alive_tm = getticks();
/* Keep track of the surviving process in the update descriptor from now on. */
rpupd->rp = surviving_rp;

View file

@ -22,7 +22,7 @@ int init_service(struct rproc *rp, int type, int flags)
endpoint_t old_endpoint;
rp->r_flags |= RS_INITIALIZING; /* now initializing */
getticks(&rp->r_alive_tm);
rp->r_alive_tm = getticks();
rp->r_check_tm = rp->r_alive_tm + 1; /* expect reply within period */
/* In case of RS initialization, we are done. */

View file

@ -2674,8 +2674,6 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
{
/* Initialize.
*/
int r;
clock_t now;
if (env_argc > 1)
optset_parse(optset_table, env_argv[1]);
@ -2689,10 +2687,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
if (driver_minor > 255)
panic("invalid or no driver minor given");
if ((r = getticks(&now)) != OK)
panic("unable to get uptime: %d", r);
srand48(now);
srand48(getticks());
output("BLOCKTEST: driver label '%s' (endpt %d), minor %d\n",
driver_label, driver_endpt, driver_minor);