summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-12-03 22:12:50 -0700
committerAndreas Kling <kling@serenityos.org>2020-12-21 18:26:12 +0100
commit5f51d851840d889520c21cc4359d6db59d83ff06 (patch)
tree2edf3477ba3500c770353461480500c8cda01efd /Libraries
parenta3fdf5148bb8f7760eea863eb13cb9264da054a6 (diff)
downloadserenity-5f51d851840d889520c21cc4359d6db59d83ff06.zip
Kernel: Improve time keeping and dramatically reduce interrupt load
This implements a number of changes related to time: * If a HPET is present, it is now used only as a system timer, unless the Local APIC timer is used (in which case the HPET timer will not trigger any interrupts at all). * If a HPET is present, the current time can now be as accurate as the chip can be, independently from the system timer. We now query the HPET main counter for the current time in CPU #0's system timer interrupt, and use that as a base line. If a high precision time is queried, that base line is used in combination with quering the HPET timer directly, which should give a much more accurate time stamp at the expense of more overhead. For faster time stamps, the more coarse value based on the last interrupt will be returned. This also means that any missed interrupts should not cause the time to drift. * The default system interrupt rate is reduced to about 250 per second. * Fix calculation of Thread CPU usage by using the amount of ticks they used rather than the number of times a context switch happened. * Implement CLOCK_REALTIME_COARSE and CLOCK_MONOTONIC_COARSE and use it for most cases where precise timestamps are not needed.
Diffstat (limited to 'Libraries')
-rw-r--r--Libraries/LibC/time.h3
-rw-r--r--Libraries/LibC/unistd.cpp4
-rw-r--r--Libraries/LibCore/ElapsedTimer.cpp4
-rw-r--r--Libraries/LibCore/ElapsedTimer.h6
-rw-r--r--Libraries/LibCore/EventLoop.cpp6
-rw-r--r--Libraries/LibCore/ProcessStatisticsReader.cpp3
-rw-r--r--Libraries/LibCore/ProcessStatisticsReader.h3
-rw-r--r--Libraries/LibPthread/pthread.cpp4
-rw-r--r--Libraries/LibPthread/pthread.h6
9 files changed, 24 insertions, 15 deletions
diff --git a/Libraries/LibC/time.h b/Libraries/LibC/time.h
index 24c1c10b83..05fcb883d3 100644
--- a/Libraries/LibC/time.h
+++ b/Libraries/LibC/time.h
@@ -72,6 +72,9 @@ typedef int clockid_t;
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
+#define CLOCK_MONOTONIC_RAW 4
+#define CLOCK_REALTIME_COARSE 5
+#define CLOCK_MONOTONIC_COARSE 6
#define TIMER_ABSTIME 99
int clock_gettime(clockid_t, struct timespec*);
diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp
index edcedd20de..65a74f54b5 100644
--- a/Libraries/LibC/unistd.cpp
+++ b/Libraries/LibC/unistd.cpp
@@ -339,7 +339,7 @@ char* getwd(char* buf)
int sleep(unsigned seconds)
{
struct timespec ts = { seconds, 0 };
- if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, nullptr) < 0)
+ if (clock_nanosleep(CLOCK_MONOTONIC_COARSE, 0, &ts, nullptr) < 0)
return ts.tv_sec;
return 0;
}
@@ -347,7 +347,7 @@ int sleep(unsigned seconds)
int usleep(useconds_t usec)
{
struct timespec ts = { (long)(usec / 1000000), (long)(usec % 1000000) * 1000 };
- return clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, nullptr);
+ return clock_nanosleep(CLOCK_MONOTONIC_COARSE, 0, &ts, nullptr);
}
int gethostname(char* buffer, size_t size)
diff --git a/Libraries/LibCore/ElapsedTimer.cpp b/Libraries/LibCore/ElapsedTimer.cpp
index 1d7d37009d..9d0fc95378 100644
--- a/Libraries/LibCore/ElapsedTimer.cpp
+++ b/Libraries/LibCore/ElapsedTimer.cpp
@@ -36,7 +36,7 @@ void ElapsedTimer::start()
{
m_valid = true;
timespec now_spec;
- clock_gettime(CLOCK_MONOTONIC, &now_spec);
+ clock_gettime(m_precise ? CLOCK_MONOTONIC : CLOCK_MONOTONIC_COARSE, &now_spec);
m_origin_time.tv_sec = now_spec.tv_sec;
m_origin_time.tv_usec = now_spec.tv_nsec / 1000;
}
@@ -46,7 +46,7 @@ int ElapsedTimer::elapsed() const
ASSERT(is_valid());
struct timeval now;
timespec now_spec;
- clock_gettime(CLOCK_MONOTONIC, &now_spec);
+ clock_gettime(m_precise ? CLOCK_MONOTONIC : CLOCK_MONOTONIC_COARSE, &now_spec);
now.tv_sec = now_spec.tv_sec;
now.tv_usec = now_spec.tv_nsec / 1000;
struct timeval diff;
diff --git a/Libraries/LibCore/ElapsedTimer.h b/Libraries/LibCore/ElapsedTimer.h
index 4759c0ede0..224eb139e3 100644
--- a/Libraries/LibCore/ElapsedTimer.h
+++ b/Libraries/LibCore/ElapsedTimer.h
@@ -32,7 +32,10 @@ namespace Core {
class ElapsedTimer {
public:
- ElapsedTimer() { }
+ ElapsedTimer(bool precise = false)
+ : m_precise(precise)
+ {
+ }
bool is_valid() const { return m_valid; }
void start();
@@ -41,6 +44,7 @@ public:
const struct timeval& origin_time() const { return m_origin_time; }
private:
+ bool m_precise { false };
bool m_valid { false };
struct timeval m_origin_time {
0, 0
diff --git a/Libraries/LibCore/EventLoop.cpp b/Libraries/LibCore/EventLoop.cpp
index 646e8d3e8c..4e45d3852f 100644
--- a/Libraries/LibCore/EventLoop.cpp
+++ b/Libraries/LibCore/EventLoop.cpp
@@ -580,7 +580,7 @@ retry:
auto next_timer_expiration = get_next_timer_expiration();
if (next_timer_expiration.has_value()) {
timespec now_spec;
- clock_gettime(CLOCK_MONOTONIC, &now_spec);
+ clock_gettime(CLOCK_MONOTONIC_COARSE, &now_spec);
now.tv_sec = now_spec.tv_sec;
now.tv_usec = now_spec.tv_nsec / 1000;
timeval_sub(next_timer_expiration.value(), now, timeout);
@@ -631,7 +631,7 @@ try_select_again:
if (!s_timers->is_empty()) {
timespec now_spec;
- clock_gettime(CLOCK_MONOTONIC, &now_spec);
+ clock_gettime(CLOCK_MONOTONIC_COARSE, &now_spec);
now.tv_sec = now_spec.tv_sec;
now.tv_usec = now_spec.tv_nsec / 1000;
}
@@ -709,7 +709,7 @@ int EventLoop::register_timer(Object& object, int milliseconds, bool should_relo
timer->interval = milliseconds;
timeval now;
timespec now_spec;
- clock_gettime(CLOCK_MONOTONIC, &now_spec);
+ clock_gettime(CLOCK_MONOTONIC_COARSE, &now_spec);
now.tv_sec = now_spec.tv_sec;
now.tv_usec = now_spec.tv_nsec / 1000;
timer->reload(now);
diff --git a/Libraries/LibCore/ProcessStatisticsReader.cpp b/Libraries/LibCore/ProcessStatisticsReader.cpp
index 69928d5b46..5a0ff949c6 100644
--- a/Libraries/LibCore/ProcessStatisticsReader.cpp
+++ b/Libraries/LibCore/ProcessStatisticsReader.cpp
@@ -85,7 +85,8 @@ HashMap<pid_t, Core::ProcessStatistics> ProcessStatisticsReader::get_all()
thread.times_scheduled = thread_object.get("times_scheduled").to_u32();
thread.name = thread_object.get("name").to_string();
thread.state = thread_object.get("state").to_string();
- thread.ticks = thread_object.get("ticks").to_u32();
+ thread.ticks_user = thread_object.get("ticks_user").to_u32();
+ thread.ticks_kernel = thread_object.get("ticks_kernel").to_u32();
thread.cpu = thread_object.get("cpu").to_u32();
thread.priority = thread_object.get("priority").to_u32();
thread.effective_priority = thread_object.get("effective_priority").to_u32();
diff --git a/Libraries/LibCore/ProcessStatisticsReader.h b/Libraries/LibCore/ProcessStatisticsReader.h
index 3afcac4f60..9c3bd93a80 100644
--- a/Libraries/LibCore/ProcessStatisticsReader.h
+++ b/Libraries/LibCore/ProcessStatisticsReader.h
@@ -35,7 +35,8 @@ namespace Core {
struct ThreadStatistics {
pid_t tid;
unsigned times_scheduled;
- unsigned ticks;
+ unsigned ticks_user;
+ unsigned ticks_kernel;
unsigned syscall_count;
unsigned inode_faults;
unsigned zero_faults;
diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp
index fd53b91fb7..74fcab0302 100644
--- a/Libraries/LibPthread/pthread.cpp
+++ b/Libraries/LibPthread/pthread.cpp
@@ -474,7 +474,7 @@ int pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* attr)
{
cond->value = 0;
cond->previous = 0;
- cond->clockid = attr ? attr->clockid : CLOCK_MONOTONIC;
+ cond->clockid = attr ? attr->clockid : CLOCK_MONOTONIC_COARSE;
return 0;
}
@@ -502,7 +502,7 @@ int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
int pthread_condattr_init(pthread_condattr_t* attr)
{
- attr->clockid = CLOCK_MONOTONIC;
+ attr->clockid = CLOCK_MONOTONIC_COARSE;
return 0;
}
diff --git a/Libraries/LibPthread/pthread.h b/Libraries/LibPthread/pthread.h
index 9c6888c233..f397367054 100644
--- a/Libraries/LibPthread/pthread.h
+++ b/Libraries/LibPthread/pthread.h
@@ -82,9 +82,9 @@ int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param
{ \
0, 0, 0, PTHREAD_MUTEX_DEFAULT \
}
-#define PTHREAD_COND_INITIALIZER \
- { \
- 0, 0, CLOCK_MONOTONIC \
+#define PTHREAD_COND_INITIALIZER \
+ { \
+ 0, 0, CLOCK_MONOTONIC_COARSE \
}
int pthread_key_create(pthread_key_t* key, void (*destructor)(void*));