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:
parent
b5c2cdafb2
commit
ac4a0becd2
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
11
src/queues.c
11
src/queues.c
@ -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);
|
||||||
|
18
src/utils.c
18
src/utils.c
@ -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: */
|
||||||
|
@ -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: */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user