Count monotonic time with Linux specific clocks

On Linux, CLOCK_MONOTONIC has got a bug. It does not count
onwards during sleep, albeit required by POSIX. This behavior
is reasoned with the requirement for poll().
Also the GLib people are sticking to this behavior in their
g_get_monotonic_time() function.

So we have to use a drop in replacement, which respects CLOCK_BOOTTIME
on Linux, as this is the clock, what would be CLOCK_MONOTONIC on POSIX
systems.
This commit is contained in:
Benedikt Heine 2018-03-20 10:57:40 +01:00
parent b5c2cdafb2
commit ac4a0becd2
5 changed files with 37 additions and 8 deletions

View File

@ -19,6 +19,7 @@
#include "option_parser.h" #include "option_parser.h"
#include "queues.h" #include "queues.h"
#include "settings.h" #include "settings.h"
#include "utils.h"
#include "x11/screen.h" #include "x11/screen.h"
#include "x11/x.h" #include "x11/x.h"
@ -70,7 +71,7 @@ static gboolean run(void *data)
} }
if (xctx.visible) { if (xctx.visible) {
gint64 now = g_get_monotonic_time(); gint64 now = time_monotonic_now();
gint64 sleep = queues_get_next_datachange(now); gint64 sleep = queues_get_next_datachange(now);
gint64 timeout_at = now + sleep; gint64 timeout_at = now + sleep;

View File

@ -290,7 +290,7 @@ notification *notification_create(void)
n->markup = settings.markup; n->markup = settings.markup;
n->format = settings.format; n->format = settings.format;
n->timestamp = g_get_monotonic_time(); n->timestamp = time_monotonic_now();
n->urgency = URG_NORM; n->urgency = URG_NORM;
n->timeout = -1; n->timeout = -1;
@ -528,7 +528,7 @@ void notification_update_text_to_render(notification *n)
/* print age */ /* print age */
gint64 hours, minutes, seconds; gint64 hours, minutes, seconds;
gint64 t_delta = g_get_monotonic_time() - n->timestamp; gint64 t_delta = time_monotonic_now() - n->timestamp;
if (settings.show_age_threshold >= 0 if (settings.show_age_threshold >= 0
&& t_delta >= settings.show_age_threshold) { && t_delta >= settings.show_age_threshold) {

View File

@ -23,6 +23,7 @@
#include "log.h" #include "log.h"
#include "notification.h" #include "notification.h"
#include "settings.h" #include "settings.h"
#include "utils.h"
/* notification lists */ /* notification lists */
static GQueue *waiting = NULL; /**< all new notifications get into here */ static GQueue *waiting = NULL; /**< all new notifications get into here */
@ -133,7 +134,7 @@ static bool queues_stack_duplicate(notification *n)
iter->data = n; iter->data = n;
n->start = g_get_monotonic_time(); n->start = time_monotonic_now();
n->dup_count = orig->dup_count; n->dup_count = orig->dup_count;
@ -180,7 +181,7 @@ bool queues_notification_replace_id(notification *new)
notification *old = iter->data; notification *old = iter->data;
if (old->id == new->id) { if (old->id == new->id) {
iter->data = new; iter->data = new;
new->start = g_get_monotonic_time(); new->start = time_monotonic_now();
new->dup_count = old->dup_count; new->dup_count = old->dup_count;
notification_run_script(new); notification_run_script(new);
notification_free(old); notification_free(old);
@ -305,7 +306,7 @@ void queues_check_timeouts(bool idle, bool fullscreen)
/* don't timeout when user is idle */ /* don't timeout when user is idle */
if (is_idle && !n->transient) { if (is_idle && !n->transient) {
n->start = g_get_monotonic_time(); n->start = time_monotonic_now();
continue; continue;
} }
@ -315,7 +316,7 @@ void queues_check_timeouts(bool idle, bool fullscreen)
} }
/* remove old message */ /* remove old message */
if (g_get_monotonic_time() - n->start > n->timeout) { if (time_monotonic_now() - n->start > n->timeout) {
queues_notification_close(n, REASON_TIME); queues_notification_close(n, REASON_TIME);
} }
} }
@ -368,7 +369,7 @@ void queues_update(bool fullscreen)
continue; continue;
} }
n->start = g_get_monotonic_time(); n->start = time_monotonic_now();
if (!n->redisplayed && n->script) { if (!n->redisplayed && n->script) {
notification_run_script(n); notification_run_script(n);

View File

@ -7,6 +7,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#include "log.h" #include "log.h"
@ -166,4 +167,21 @@ gint64 string_to_time(const char *string)
return 0; return 0;
} }
/* see utils.h */
gint64 time_monotonic_now(void)
{
struct timespec tv_now;
/* On Linux, BOOTTIME is the correct monotonic time,
* as BOOTTIME counts onwards during sleep. For all other
* POSIX compliant OSes, MONOTONIC should also count onwards
* during system sleep. */
#ifdef __linux__
clock_gettime(CLOCK_BOOTTIME, &tv_now);
#else
clock_gettime(CLOCK_MONOTONIC, &tv_now);
#endif
return (gint64)tv_now.tv_sec * G_USEC_PER_SEC
+ tv_now.tv_nsec / 1000;
}
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -27,5 +27,14 @@ char *string_to_path(char *string);
/* convert time units (ms, s, m) to internal gint64 microseconds */ /* convert time units (ms, s, m) to internal gint64 microseconds */
gint64 string_to_time(const char *string); gint64 string_to_time(const char *string);
/**
* Get the current monotonic time. In contrast to `g_get_monotonic_time`,
* this function respects the real monotonic time of the system and
* counts onwards during system sleep.
*
* @returns: A `gint64` monotonic time representation
*/
gint64 time_monotonic_now(void);
#endif #endif
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */