Browse Source

TT#101202 keep timer queue entries with same timestamp in order

closes #1110

Change-Id: Ia121deb9589bfdfa112189b22d4a78bdb29c535b
pull/1116/head
Richard Fuchs 5 years ago
parent
commit
f393d29009
4 changed files with 46 additions and 6 deletions
  1. +35
    -1
      daemon/timerthread.c
  2. +1
    -0
      include/timerthread.h
  3. +9
    -5
      lib/auxlib.c
  4. +1
    -0
      lib/auxlib.h

+ 35
- 1
daemon/timerthread.c View File

@ -158,7 +158,14 @@ static void __timerthread_queue_free(void *p) {
static int ttqe_compare(const void *a, const void *b) {
const struct timerthread_queue_entry *t1 = a;
const struct timerthread_queue_entry *t2 = b;
return timeval_cmp_ptr(&t1->when, &t2->when);
int ret = timeval_cmp_zero(&t1->when, &t2->when);
if (ret)
return ret;
if (t1->idx < t2->idx)
return -1;
if (t1->idx == t2->idx)
return 0;
return 1;
}
void *timerthread_queue_new(const char *type, size_t size,
@ -183,6 +190,18 @@ void *timerthread_queue_new(const char *type, size_t size,
return ttq;
}
int __ttqe_find_last_idx(const void *a, const void *b) {
const struct timerthread_queue_entry *ttqe_a = a;
void **data = (void **) b;
const struct timerthread_queue_entry *ttqe_b = data[0];
int ret = timeval_cmp(&ttqe_b->when, &ttqe_a->when);
if (ret)
return ret;
// same timestamp. track highest seen idx
if (GPOINTER_TO_UINT(data[1]) < ttqe_a->idx)
data[1] = GUINT_TO_POINTER(ttqe_a->idx);
return 1; // and continue to higher idx
}
void timerthread_queue_push(struct timerthread_queue *ttq, struct timerthread_queue_entry *ttqe) {
// can we send immediately?
if (ttq->run_now_func && timerthread_queue_run_one(ttq, ttqe, ttq->run_now_func) == 0)
@ -203,7 +222,22 @@ void timerthread_queue_push(struct timerthread_queue *ttq, struct timerthread_qu
// ntohs(rh->seq_num),
// ntohl(rh->timestamp));
ttqe->idx = 0;
mutex_lock(&ttq->lock);
// check for most common case: no timestamp collision exists
if (!g_tree_lookup(ttq->entries, ttqe))
;
else {
// something else exists with the same timestamp. find the highest idx
void *data[2];
data[0] = ttqe;
data[1] = 0;
g_tree_search(ttq->entries, __ttqe_find_last_idx, data);
ttqe->idx = GPOINTER_TO_UINT(data[1] + 1);
}
// this hands over ownership of cp, so we must copy the timeval out
struct timeval tv_send = ttqe->when;
g_tree_insert(ttq->entries, ttqe, ttqe);


+ 1
- 0
include/timerthread.h View File

@ -35,6 +35,7 @@ struct timerthread_queue {
struct timerthread_queue_entry {
struct timeval when;
unsigned int idx; // for equal timestamps
void *source; // opaque
char __rest[0];
};


+ 9
- 5
lib/auxlib.c View File

@ -363,9 +363,8 @@ int uint32_eq(const void *a, const void *b) {
return (*A == *B) ? TRUE : FALSE;
}
int timeval_cmp_ptr(const void *a, const void *b) {
int timeval_cmp_zero(const void *a, const void *b) {
const struct timeval *A = a, *B = b;
int ret;
/* zero timevals go last */
if (A->tv_sec == 0 && B->tv_sec != 0)
@ -373,13 +372,18 @@ int timeval_cmp_ptr(const void *a, const void *b) {
if (B->tv_sec == 0 && A->tv_sec == 0)
return -1;
if (A->tv_sec == 0 && B->tv_sec == 0)
goto ptr;
return 0;
/* earlier timevals go first */
ret = timeval_cmp(A, B);
return timeval_cmp(A, B);
}
int timeval_cmp_ptr(const void *a, const void *b) {
const struct timeval *A = a, *B = b;
int ret;
ret = timeval_cmp_zero(A, B);
if (ret)
return ret;
/* equal timeval, so use pointer as tie breaker */
ptr:
if (A < B)
return -1;
if (A > B)


+ 1
- 0
lib/auxlib.h View File

@ -260,6 +260,7 @@ INLINE int timeval_cmp(const struct timeval *a, const struct timeval *b) {
return long_cmp(a->tv_usec, b->tv_usec);
}
// as a GCompareFunc
int timeval_cmp_zero(const void *a, const void *b);
int timeval_cmp_ptr(const void *a, const void *b);
INLINE void timeval_lowest(struct timeval *l, const struct timeval *n) {


Loading…
Cancel
Save