aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhaoming Luo <zhmingluo@163.com>2024-12-24 09:57:51 +0800
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2024-12-29 02:22:29 +0100
commitfc494bfe3fb6363e1077dc035eb119970d84a9d1 (patch)
tree271db20499a280503ad5b046436fd9dd54dd5b25
parent0bd3b64ff3af9a7c1b65bafb5cbf5189c52dc85a (diff)
downloadgnumach-fc494bfe3fb6363e1077dc035eb119970d84a9d1.tar.gz
gnumach-fc494bfe3fb6363e1077dc035eb119970d84a9d1.tar.bz2
gnumach-fc494bfe3fb6363e1077dc035eb119970d84a9d1.zip
kern: Add a mach host operation which returns elapsed time since bootup
Add host_get_uptime64() mach interface operation. It can be used to get the time passed since the boot up. * doc/mach.texi: Add the documentation for the operation * include/mach/mach_host.defs: Add the interface * include/mach/time_value.h: Extend the mappable time variable * kern/mach_clock.c: Operation implementation * kern/mach_clock.h: Add a new variable for storing uptime Signed-off-by: Zhaoming Luo <zhmingluo@163.com> Message-ID: <20241224015751.1282-1-zhmingluo@163.com>
-rw-r--r--doc/mach.texi5
-rw-r--r--include/mach/mach_host.defs7
-rw-r--r--include/mach/time_value.h2
-rw-r--r--kern/mach_clock.c39
-rw-r--r--kern/mach_clock.h1
5 files changed, 54 insertions, 0 deletions
diff --git a/doc/mach.texi b/doc/mach.texi
index f85288e0..f54ed655 100644
--- a/doc/mach.texi
+++ b/doc/mach.texi
@@ -5664,6 +5664,11 @@ Get the current time as seen by @var{host}. On success, the time passed
since the epoch is returned in @var{current_time}.
@end deftypefun
+@deftypefun kern_return_t host_get_uptime64 (@w{host_t @var{host}}, @w{time_value64_t *@var{uptime}})
+Get the elapsed time since the boot up as seen by @var{host}. On success, the time passed
+since the boot up is returned in @var{uptime}.
+@end deftypefun
+
@deftypefun kern_return_t host_set_time64 (@w{host_priv_t @var{host_priv}}, @w{time_value64_t @var{new_time}})
Set the time of @var{host_priv} to @var{new_time}.
@end deftypefun
diff --git a/include/mach/mach_host.defs b/include/mach/mach_host.defs
index 8fd9d6b3..501ca0f6 100644
--- a/include/mach/mach_host.defs
+++ b/include/mach/mach_host.defs
@@ -386,3 +386,10 @@ routine host_adjust_time64(
routine host_get_kernel_version(
host : host_t;
out kernel_version : new_kernel_version_t);
+
+/*
+ * Get the uptime on this host.
+ */
+routine host_get_uptime64(
+ host : host_t;
+ out uptime : time_value64_t);
diff --git a/include/mach/time_value.h b/include/mach/time_value.h
index e08707bc..7378c2cf 100644
--- a/include/mach/time_value.h
+++ b/include/mach/time_value.h
@@ -172,6 +172,8 @@ typedef struct mapped_time_value {
integer_t check_seconds;
struct time_value64 time_value;
int64_t check_seconds64;
+ struct time_value64 uptime_value;
+ int64_t check_upseconds64;
} mapped_time_value_t;
/* Macros for converting between struct timespec and time_value_t. */
diff --git a/kern/mach_clock.c b/kern/mach_clock.c
index 24609353..5501b7b8 100644
--- a/kern/mach_clock.c
+++ b/kern/mach_clock.c
@@ -69,6 +69,7 @@
int hz = HZ; /* number of ticks per second */
int tick = (MICROSECONDS_IN_ONE_SECOND / HZ); /* number of usec per tick */
time_value64_t time = { 0, 0 }; /* wallclock time (unadjusted) */
+time_value64_t uptime = { 0, 0 }; /* time since bootup */
unsigned long elapsed_ticks = 0; /* ticks elapsed since bootup */
int timedelta = 0;
@@ -109,6 +110,17 @@ MACRO_BEGIN \
} \
MACRO_END
+#define update_mapped_uptime(uptime) \
+MACRO_BEGIN \
+ if (mtime != 0) { \
+ mtime->check_upseconds64 = (uptime)->seconds; \
+ __sync_synchronize(); \
+ mtime->uptime_value.nanoseconds = (uptime)->nanoseconds;\
+ __sync_synchronize(); \
+ mtime->uptime_value.seconds = (uptime)->seconds; \
+ } \
+MACRO_END
+
#define read_mapped_time(time) \
MACRO_BEGIN \
do { \
@@ -119,6 +131,16 @@ MACRO_BEGIN \
} while ((time)->seconds != mtime->check_seconds64); \
MACRO_END
+#define read_mapped_uptime(uptime) \
+MACRO_BEGIN \
+ do { \
+ (uptime)->seconds = mtime->uptime_value.seconds; \
+ __sync_synchronize(); \
+ (uptime)->nanoseconds = mtime->uptime_value.nanoseconds;\
+ __sync_synchronize(); \
+ } while ((uptime)->seconds != mtime->check_upseconds64); \
+MACRO_END
+
def_simple_lock_irq_data(static, timer_lock) /* lock for ... */
timer_elt_data_t timer_head; /* ordered list of timeouts */
/* (doubles as end-of-list) */
@@ -230,6 +252,7 @@ void clock_interrupt(
*/
if (timedelta == 0) {
time_value64_add_nanos(&time, usec * 1000);
+ time_value64_add_nanos(&uptime, usec * 1000);
}
else {
int delta;
@@ -251,8 +274,10 @@ void clock_interrupt(
timedelta -= tickdelta;
}
time_value64_add_nanos(&time, delta * 1000);
+ time_value64_add_nanos(&uptime, delta * 1000);
}
update_mapped_time(&time);
+ update_mapped_uptime(&uptime);
/*
* Schedule soft-interrupt for timeout if needed
@@ -571,6 +596,19 @@ host_adjust_time64(
return (KERN_SUCCESS);
}
+/*
+ * Read the uptime (the elapsed time since boot up).
+ */
+kern_return_t
+host_get_uptime64(const host_t host, time_value64_t *uptime)
+{
+ if (host == HOST_NULL)
+ return (KERN_INVALID_HOST);
+
+ read_mapped_uptime(uptime);
+ return (KERN_SUCCESS);
+}
+
void mapable_time_init(void)
{
if (kmem_alloc_wired(kernel_map, (vm_offset_t *) &mtime, PAGE_SIZE)
@@ -578,6 +616,7 @@ void mapable_time_init(void)
panic("mapable_time_init");
memset((void *) mtime, 0, PAGE_SIZE);
update_mapped_time(&time);
+ update_mapped_uptime(&uptime);
}
int timeopen(dev_t dev, int flag, io_req_t ior)
diff --git a/kern/mach_clock.h b/kern/mach_clock.h
index 04ed4b99..d4f04f5e 100644
--- a/kern/mach_clock.h
+++ b/kern/mach_clock.h
@@ -41,6 +41,7 @@ extern int hz; /* number of ticks per second */
extern int tick; /* number of usec per tick */
extern time_value64_t time; /* wallclock time (unadjusted) */
+extern time_value64_t uptime; /* time since bootup */
typedef void timer_func_t(void *);